亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript中Promise處理異步的并行與串行

 更新時間:2022年12月19日 07:32:41   作者:東方淼淼  
js中的promise是一個異步編程的解決方案,語法層面上他是一個構(gòu)造函數(shù),名字為Promise(),下面這篇文章主要給大家介紹了關(guān)于JavaScript中Promise處理異步的并行與串行的相關(guān)資料,需要的朋友可以參考下

一、異步的“并行”

同時處理,相互之間沒啥依賴

// 執(zhí)行FN1返回一個promise實例,實例中管理了一個異步編程的代碼,當(dāng)定時器到時間后,才會把實例的狀態(tài)改為成功
const fn1 = () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(1);
        }, 1000);
    });
};
const fn2 = () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(2);
        }, 2000);
    });
};
const fn3 = () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(3);
        }, 3000);
    });
}; 


// 異步的“并行”:同時處理,相互之間沒啥依賴
fn1().then(result => {
    console.log(result);
});
fn2().then(result => {
    console.log(result);
});
fn3().then(result => {
    console.log(result);
}); 

 并行中的綜合處理

一起發(fā)送多個請求(處理多個異步),但是需要等到所有異步都成功,我們再整體做啥事!!

  • 語法:let promise = Promise.all([promise1,promise2,...]);

  • 執(zhí)行Promise.all返回一個新的promise實例 @P

    • 并且傳遞一個數(shù)組,數(shù)組中包含N多其它的promise實例

    •  如果數(shù)組中的每一個promise實例最后都是成功的,則@P也將會是成功的,它的值也是一個數(shù)組,按照順序依次存儲各個promise實例的結(jié)果;但凡數(shù)組中的某個promsie實例是失敗的,則@P也是失敗的,值是當(dāng)前這個實例失敗的原因!

    •  如果數(shù)組中有一項并不是promise實例(例如:是個100),則瀏覽器也會把其默認(rèn)變?yōu)橐粋€狀態(tài)是成功的promsie實例,值就是當(dāng)前項本身

let p = Promise.all([Promise.resolve(100), fn1(), 200, fn3(), fn2()]); //瀏覽器默認(rèn)會把200 變?yōu)橐粋€成功的promsie實例
p.then(results => {
    console.log(`成功:${results}`); // 成功:100,1,200,3,2 順序和最開始是一致的,不會考慮誰先成功
}).catch(reason => {
    console.log(`失?。?{reason}`);
}); 

//new Error('xxx')不是promise實例=》Promise.resolve(new Error('xxx')) 值是Error對象
let p = Promise.all([Promise.resolve(100), fn1(), new Error('xxx'), Promise.reject(200), fn3(), fn2()]);
p.then(results => {
    console.log(`成功:${results}`);
}).catch(reason => {
    console.log(`失?。?{reason}`); //失?。?00 遇到錯誤直接返回
}); 

//=>等三個異步都成功做什么事情 所用時間3s
Promise.all([fn1(), fn2(), fn3()]).then(results => {
    console.log(`三個異步都成功了,分別的結(jié)果:${results}`);
}); 

二、異步的“串行”:

第一個異步成功才能發(fā)送第二個,第二個成功才能發(fā)送第三個....多個異步之間一般是有依賴的

2.1 then鏈機(jī)制處理

promise狀態(tài)是失敗,如果不用catch(或者onrejected)處理,控制臺會拋出異常:Uncaught (in promise) xxx,但是此異常不會阻礙下面代碼執(zhí)行!!

fn1().then(result => {
    console.log(`第一個成功:${result}`);
    return fn2();
}).then(result => {
    console.log(`第二個成功:${result}`);
    return fn3();
}).then(result => {
    console.log(`第三個成功:${result}`);
}).catch(reason => {
    console.log(`只要其中一個失敗,直接順延到這里,其余剩下的請求就不發(fā)送了!`);
});

2.2 真實項目中,想實現(xiàn)異步的串行,我們一般使用async+await

(async function () {
    let result = await fn1();
    console.log(`第一個成功:${result}`);

    result = await fn2();
    console.log(`第二個成功:${result}`);

    result = await fn3();
    console.log(`第三個成功:${result}`);
})();

2.3 promise.then(onfulfilled,onrejected) 在內(nèi)存中的執(zhí)行

首先,我們復(fù)習(xí)一下事件循環(huán)機(jī)制 EventLoop

  • 同步代碼執(zhí)行,遇到一個異步任務(wù)

    • 1. 先把其放在 WebAPI 進(jìn)行監(jiān)聽

    • 2. 當(dāng)前異步任務(wù)監(jiān)聽到可以執(zhí)行了,則再把其放在EventQueue中,排隊等待執(zhí)行

  • 同步任務(wù)執(zhí)行完,主線程空閑下來

    •  1. 去EventQueue中找可執(zhí)行的微任務(wù),如果微任務(wù)中都執(zhí)行完了,再去找可執(zhí)行的宏任務(wù)「隊列:優(yōu)先級隊列 & 先進(jìn)先出」

    • 2. 取到的任務(wù)都放在Stack中交給主線程去執(zhí)行

    •  ......

那么接下來我們來了解一下promise.then(onfulfilled,onrejected) 在內(nèi)存中的執(zhí)行

promise.then(onfulfilled,onrejected) 在內(nèi)存中的執(zhí)行

  • 情況一:我此時已經(jīng)知道promise是成功還是失敗的

    •  我們此時應(yīng)該去執(zhí)行onfulfilled或者onrejected,但是不是立即執(zhí)行,它是一個異步的微任務(wù)

    • 首先把執(zhí)行對應(yīng)的方法這個事情放在WebAPI中監(jiān)聽,但是因為此時已經(jīng)知道狀態(tài)了,對應(yīng)的方法肯定可以執(zhí)行,所以緊接著把它挪至到EventQueue中「異步微任務(wù)隊列」等待執(zhí)行

  • 情況二:此時的promise還是pending狀態(tài)

    •  我們把onfulfilled/onrejected先存儲起來,只有當(dāng)后面,我們把實例的狀態(tài)修改為成功/失敗的時候,再取出之前存儲的方法,把其執(zhí)行「而且此時再執(zhí)行,還是個異步微任務(wù)」

    • 還是要經(jīng)歷:WebAPI -> EventQueue

三、aysnc修飾符

aysnc最主要的作用就是:如果想在函數(shù)中使用await,則當(dāng)前函數(shù)必須基于async修飾

aysnc修飾符,讓函數(shù)的返回值成為一個promise實例 這樣就可以基于THEN鏈去處理了

  • 如果函數(shù)自己本身就返回一個promise實例,則以自己返回的為主

  • 如果函數(shù)自己本身沒有返回promise,則會把返回值變?yōu)橐粋€promise實例:狀態(tài)=> 成功 值=>返回值

  • 如果函數(shù)執(zhí)行報錯則返回的實例狀態(tài)是失敗,值是報錯原因,但不影響下面代碼執(zhí)行

async function fn() {
    return 10;
}
fn().then(result => {
    console.log(result);//輸出10
}); 

async function fn() {
    return async function () {
        return 10;
    };
}
fn().then(result => {
    // result:async function () {...}  函數(shù)
    return result();
}).then(result => {
    console.log(result); //10
}); 

四、await:等待

  • 我們一般在其后面放promise實例 它會等待實例狀態(tài)為成功,再去執(zhí)行“當(dāng)前上下文”中 ,await下面的代碼

【如果promise實例管控的是一個異步編程,其實它是在等待異步成功,再執(zhí)行下面的代碼,類似于把異步改為同步的效果】

  • await 10 =>默認(rèn)轉(zhuǎn)為 await Promise.resolve(10)

    • 如果后面放的不是promise實例,則瀏覽器默認(rèn)把其轉(zhuǎn)換為”狀態(tài)為成功,值就是這個值 " 的實例
const fn1 = () => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(1);
        }, 1000);
    });
};
(async function () {
    let result = await fn1();
    console.log(result); 
  //下面代碼可以執(zhí)行,說明await后面的promise實例,它的狀態(tài)已經(jīng)是成功了,await的返回值就是當(dāng)前promise實例的值
    console.log('OK');
})(); 


//=======================如果await后面的promise實例狀態(tài)是失敗的
const fn1 = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject(0);
        }, 1000);
    });
};
(async function () {
    let result = await fn1(); //如果await后面的promise實例狀態(tài)是失敗的,則下面代碼永遠(yuǎn)都不會執(zhí)行了
    console.log(result);
    console.log('OK');//如果是失敗的則這句話不會執(zhí)行
})();

//===================================================
(async function () {
    let a = await 10; //->Promise.resolve(10)
    console.log(a); //10
    let b = await Promise.resolve(20);
    console.log(b); //20
    try {
        let c = await Promise.reject(30); //Uncaught (in promise) 30
        console.log(c);
    } catch (err) {
        console.log(err); //30
    }
    console.log('OK'); //'OK'
})(); 

await中的異步

await中的異步:當(dāng)前上下文,await下面的代碼執(zhí)行是異步微任務(wù)

  • 情況1:await后面的promise實例我們已知是成功的

    先把微任務(wù)放置在WebAPI中,但是知道是可以執(zhí)行的,則直接在挪至到EventQueue中等待執(zhí)行

  • 情況2:await后面的promise實例還是pending狀態(tài)

    此時我們把微任務(wù)放置在WebAPI中監(jiān)聽,等到后期promise實例是成功態(tài)后,再把它挪至到EventQueue中等待執(zhí)行即可 

(async function () {
    let b = await Promise.resolve(20);
    console.log(b);
})()

五、思考題

思考題1

console.log(1);
setTimeout(() => { console.log(2); });//宏1
console.log(3);
let p1 = new Promise(resolve => {//new Promise 立即會把executor函數(shù)執(zhí)行 是同步
    console.log(4);
    resolve('A'); //執(zhí)行resolve P1的狀態(tài)是成功=》已知
    console.log(5);
});
console.log(6);
p1.then(result => {//.then是異步 已知狀態(tài) 放進(jìn)WebAPI中監(jiān)聽 但是因為是已知狀態(tài) 方法肯定執(zhí)行 則從WebAPI監(jiān)聽隊列挪到EventQueue中等待
    console.log(result); //微1
});
console.log(7);
let p2 = new Promise(resolve => { //立即執(zhí)行executor函數(shù) setTimeout是異步則會放進(jìn)WebAPI監(jiān)聽 宏2
    setTimeout(() => {
        resolve('B');
        console.log(10); //執(zhí)行宏2=>@1 更改了p2的狀態(tài) @2之前存儲的.then方法執(zhí)行
    });
});
console.log(8);
p2.then(result => {//p2的狀態(tài)是未知則會先存起來
    console.log(result);
});
console.log(9);

思路及圖解

思考題2

基于事件綁定屬于異步宏任務(wù)

let body = document.body;
body.addEventListener('click', function () {
    Promise.resolve().then(() => {
        console.log(1);
    });
    console.log(2);
});
body.addEventListener('click', function () {
    Promise.resolve().then(() => {
        console.log(3);
    });
    console.log(4);
}); 

思路及圖解

思考題3

 async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
}
async function async2() {
    console.log('async2');
}
console.log('script start');
setTimeout(function () {
    console.log('setTimeout');
}, 0)
async1();
new Promise(function (resolve) {
    console.log('promise1');
    resolve();
}).then(function () {
    console.log('promise2');
});
console.log('script end'); 

思路及圖解

總結(jié)

到此這篇關(guān)于JavaScript中Promise處理異步的并行與串行的文章就介紹到這了,更多相關(guān)JS Promise異步并行與串行內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論