組織ES6模塊的時候,一般情況下我們export一些基本類型的變量返十,復(fù)合類型的對象或者函數(shù)等等妥泉。但有時模塊內(nèi)的代碼也會出現(xiàn)異步操作,我們希望模塊可以把異步操作的結(jié)果export出來供另一個模塊調(diào)用洞坑。這種情況下應(yīng)該怎么寫呢盲链?本文列舉兩種方法供參考。
利用Promise對象
export導(dǎo)出的變量類型可以是任意的Javascript對象检诗,那么我們可以利用Promise對象幫助我們代理異步操作匈仗,將Promise對象導(dǎo)出,在導(dǎo)入Promise的地方添加成功/失敗的回調(diào)即可逢慌。
a.js
import {AsyncStorage} from 'react-native';
export async function getVariable() {
let variable = await AsyncStorage.getItem("variable");
return variable;
}
b.js
import {getVariable} from 'a.js';
getVariable().then(v=>{
//在這里獲得模塊a真正想導(dǎo)出的值
}).catch(e=>{})
a文件中使用了ES7的async函數(shù)悠轩,async函數(shù)一旦執(zhí)行會立即返回一個Promise對象,等待所有await后的異步操作結(jié)束后改變Promise的狀態(tài)攻泼。如果不使用async await火架,a文件也可以這樣寫:
import {AsyncStorage} from 'react-native';
export function getVariable() {
return new Promise((resolve, reject)=>{
AsyncStorage.getItem("variable").then(v=>{
resolve(v);
}).catch(e=>{
reject(e);
})
})
}
直接導(dǎo)出異步結(jié)果
a.js
import {AsyncStorage} from 'react-native';
export var variable;
AsyncStorage.getItem("variable").then(v=>{
variable = v; //在回調(diào)函數(shù)中修改導(dǎo)出變量variable
}).catch(e=>{});
b.js
import {variable} from 'a.js';
console.log(variable); //undefined
setTimeout(()=>{
console.log(variable); //異步操作所獲得的值
}, 1000)
需要注意的是,當(dāng)采用這種方式時忙菠,要注意導(dǎo)出變量會發(fā)生變化何鸡,在引用模塊中要特別注意,否則突變的值會對程序造成莫名的bug牛欢。
說明
能夠使用上述兩種方式導(dǎo)出異步操作的結(jié)果骡男,原因就在于,ES6的模塊與CommonJS是不同的傍睹。
CommonJS 模塊輸出的是一個值的拷貝隔盛,ES6 模塊輸出的是值的引用。
阮一峰的ES6入門有如下詳細(xì)的說明:
CommonJS 模塊輸出的是值的拷貝拾稳,也就是說吮炕,一旦輸出一個值,模塊內(nèi)部的變化就影響不到這個值访得。
ES6 模塊的運(yùn)行機(jī)制與 CommonJS 不一樣龙亲。JS 引擎對腳本靜態(tài)分析的時候,遇到模塊加載命令import,就會生成一個只讀引用鳄炉。等到腳本真正執(zhí)行時杜耙,再根據(jù)這個只讀引用,到被加載的那個模塊里面去取值迎膜。換句話說泥技,ES6 的import有點(diǎn)像 Unix 系統(tǒng)的“符號連接”,原始值變了磕仅,import加載的值也會跟著變珊豹。因此,ES6 模塊是動態(tài)引用榕订,并且不會緩存值店茶,模塊里面的變量綁定其所在的模塊。