異步函數(shù)的理解
關(guān)鍵詞:異步,函數(shù)名當(dāng)參數(shù)傳遞,async/await
異步函數(shù):需要時間去處理它,這個時間可能時間比較長,為了使程序能平穩(wěn)運(yùn)行,就先跳過這個函數(shù),執(zhí)行下一步同步函數(shù).
為此,異步函數(shù)最好的例子就是人工干預(yù),增加運(yùn)行時間,沒有比setTimout()更好的例子了,以下是簡單一個示例代碼:
function delay(){
? ? ? setTimeout( ()=>{
? ? ?console.log('2S 后執(zhí)行')
? ? ?},2000)
}
delay();
console.log('同步優(yōu)先,異步靠邊,回調(diào)墊底');
// 輸出 同步優(yōu)先,異步靠邊,回調(diào)墊底 ? ?2S 后執(zhí)行
異步例子準(zhǔn)備好了, 接下來是回調(diào)函數(shù),很多教程里寫回調(diào)都用callback, 剛開始我也不明白這是什么鳥,后來才明白就是一個函數(shù)名當(dāng)參數(shù)傳遞,,還是最簡單代碼來一個.
function demo( num ,cb){
? ? num=num*2;
? ?return cb(num)
}
function ?control( number){
? ?console.log( number);
? ?return number
}
demo(100,control);
// ?輸出 200
函數(shù)當(dāng)參數(shù)名的精髓,就是主函數(shù)返回一個處理函數(shù)
像上面的 demo 就是一個標(biāo)準(zhǔn)的回調(diào)函數(shù), 回調(diào)函數(shù)的好處就是留下接口部分,通過這個接口,可以寫出更大的處理公共部分的函數(shù),
function ?anothercontrol( num){
? ?return ?num*num;
}
demo(100,anothercontrol)
//傳參是為了更多的拓展接口
回調(diào)函數(shù)還有一種常見寫法,直接寫匿名函數(shù)( function 后面不要名字,簡單粗暴);注意:公共部分的參數(shù)傳遞個數(shù)要寫正確
回調(diào)函數(shù)解決完,我們在回到異步函數(shù),思考一個問題當(dāng)異步函數(shù)遇到回調(diào)函數(shù)時執(zhí)行順序
還是直接上
function demo(num ,cb){
? ?var r = num+1;
? ?setTimeout(()=>{
? ?var z =r+3
? console.log('helllo ?2S later r:'+z)},2000);
? cb(r);
}
function other(x){
? ?var z =x*x
? console.log(x*x)
? return z
}
? demo(2,other);
先輸出9 ?2S或輸出 helllo ?2S later r:6
所以 同步優(yōu)先 異步靠邊 ,回調(diào)墊底 ,是錯誤的., 那怎么按順序執(zhí)行呢,最簡單方法是將回調(diào)函數(shù)寫入異步函數(shù)中
function demo(num ,cb){
? ?var r = num+1;
? setTimeout(()=>{
? var z =r+3
? console.log('helllo ?2S later r:'+z);
?cb(r);
?},2000)
}
OK! 不過這種方法不過方便, 如果涉及到超級多的異步函數(shù)+回調(diào)函數(shù),多層嵌套,恐怕是很頭疼的.有一個最新的好方法是使用今天的主角 ? async/await , 粗暴理解 ?異步你給我等等.
這兩天接觸這東西,是因?yàn)樽罱雽W(xué)KOA ,看了簡\書上的一些教程,綜合自己的理解寫了這個,在這感謝 @白昔月指導(dǎo),同時借鑒了@mingttong,的一些想法,當(dāng)中有很多相當(dāng)不嚴(yán)謹(jǐn),如有錯誤,歡迎私信給我
異步函數(shù)編寫
1 先要有異步的樣子 ? ?就是async, ? 在有函數(shù) ?function ,組合起來 ? async function(){}, 當(dāng)然也可以給他取名 ?async function getvalue(){}; ? ? 潮流寫法 async ()=>{}, 異步函數(shù)中可以沒有等待,但等待中一定要先說好, 因?yàn)榇蠹視r間多恨寶貴.
2 ?接著是等等 await , 等什么? 等一個函數(shù)結(jié)果 ?await function(){}, 綜合起來
async function(){
? ?await function()
}; ? ? ? ? ? ? ? //就是這么簡單,當(dāng)然坑也是無數(shù)個,接下來踩坑
代碼
async function demoAsync(){
?console.log('begin async');
? await setTimeout(()=>{
? console.log (' await coming ')
},2000);
? ?console.log ('await is end ?,now turn me')
}
demoAsync()
出結(jié)果 ?還不是我們想要的 為什么
begin async
?Promise { ?}
> await is end ?,now turn me
await coming
原理 異步等待的是一個期許(Promise) ,生活也一樣 .正確寫法
async function demoAsync(){
? ?console.log('begin async');
? await ?new Promise((resolve, reject)=>{
? setTimeout(()=>{
? ? console.log (' await coming ');
? ? ?resolve('ok');
? ?},2000);
?});
console.log ('await is end ?,now turn me');
}
demoAsync()
有了 期許 ,總是會有結(jié)果.Promise 的結(jié)果來自reslove 和 reject 兩個參數(shù)
上面代碼 返回期許的成功結(jié)果是一個字符串OK , 我們可以直接拿到 返回結(jié)果
var result ?= await new Promsie............// 這種經(jīng)常出現(xiàn)在調(diào)用數(shù)據(jù)庫異步操作取結(jié)果.
封裝一下 ?會比較好看
var ? result ?= await ? a();
接下來如何封裝起來 ?await 等待的是一個期許(Promise)記住這句,我們就返回一個期許給他
function ?pro() {
? ?return new Promise((resolve, reject)=>{
? ?setTimeout(()=>{
? console.log (' await coming ');
? ?resolve('ok');
? },2000);
? });
};
async function demoAsync(){
? ?console.log('begin async');
? ?await ?pro();
? console.log ('await is end ?,now turn me')
}
注意點(diǎn): Promise 中的 resolve 和 reject ?相當(dāng)于函數(shù)中的 return ,只是這個Promise 比較高級, 他能返回兩鐘狀態(tài). ?如果 執(zhí)行到resolve( date ), 等待就直接返回并且附帶一個結(jié)果.如果有異常該如何獲取呢, 交給reject(' wrong'),
格式
try {
? ?var result = await pro();
? ?var result2= await another();
}
catche(err){
console.log(err)
}
就是干脆,錯誤一致傳遞給catch(err),再也不用擔(dān)心異步哪出錯了