您好,登錄后才能下訂單哦!
這篇“JavaScript中Promise如何處理異步的并行與串行”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“JavaScript中Promise如何處理異步的并行與串行”文章吧。
同時處理,相互之間沒啥依賴
// 執行FN1返回一個promise實例,實例中管理了一個異步編程的代碼,當定時器到時間后,才會把實例的狀態改為成功 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); });
一起發送多個請求(處理多個異步),但是需要等到所有異步都成功,我們再整體做啥事!!
語法:let promise = Promise.all([promise1,promise2,...]);
執行Promise.all返回一個新的promise實例 @P
并且傳遞一個數組,數組中包含N多其它的promise實例
如果數組中的每一個promise實例最后都是成功的,則@P也將會是成功的,它的值也是一個數組,按照順序依次存儲各個promise實例的結果;但凡數組中的某個promsie實例是失敗的,則@P也是失敗的,值是當前這個實例失敗的原因!
如果數組中有一項并不是promise實例(例如:是個100),則瀏覽器也會把其默認變為一個狀態是成功的promsie實例,值就是當前項本身
let p = Promise.all([Promise.resolve(100), fn1(), 200, fn3(), fn2()]); //瀏覽器默認會把200 變為一個成功的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}`); //失敗:200 遇到錯誤直接返回 }); //=>等三個異步都成功做什么事情 所用時間3s Promise.all([fn1(), fn2(), fn3()]).then(results => { console.log(`三個異步都成功了,分別的結果:${results}`); });
第一個異步成功才能發送第二個,第二個成功才能發送第三個....多個異步之間一般是有依賴的
promise狀態是失敗,如果不用catch(或者onrejected)處理,控制臺會拋出異常:Uncaught (in promise) xxx,但是此異常不會阻礙下面代碼執行!!
fn1().then(result => { console.log(`第一個成功:${result}`); return fn2(); }).then(result => { console.log(`第二個成功:${result}`); return fn3(); }).then(result => { console.log(`第三個成功:${result}`); }).catch(reason => { console.log(`只要其中一個失敗,直接順延到這里,其余剩下的請求就不發送了!`); });
(async function () { let result = await fn1(); console.log(`第一個成功:${result}`); result = await fn2(); console.log(`第二個成功:${result}`); result = await fn3(); console.log(`第三個成功:${result}`); })();
首先,我們復習一下事件循環機制 EventLoop
同步代碼執行,遇到一個異步任務
1. 先把其放在 WebAPI 進行監聽
2. 當前異步任務監聽到可以執行了,則再把其放在EventQueue中,排隊等待執行
同步任務執行完,主線程空閑下來
1. 去EventQueue中找可執行的微任務,如果微任務中都執行完了,再去找可執行的宏任務「隊列:優先級隊列 & 先進先出」
2. 取到的任務都放在Stack中交給主線程去執行
......
那么接下來我們來了解一下promise.then(onfulfilled,onrejected) 在內存中的執行
promise.then(onfulfilled,onrejected) 在內存中的執行
情況一:我此時已經知道promise是成功還是失敗的
我們此時應該去執行onfulfilled或者onrejected,但是不是立即執行,它是一個異步的微任務
首先把執行對應的方法這個事情放在WebAPI中監聽,但是因為此時已經知道狀態了,對應的方法肯定可以執行,所以緊接著把它挪至到EventQueue中「異步微任務隊列」等待執行
情況二:此時的promise還是pending狀態
我們把onfulfilled/onrejected先存儲起來,只有當后面,我們把實例的狀態修改為成功/失敗的時候,再取出之前存儲的方法,把其執行「而且此時再執行,還是個異步微任務」
還是要經歷:WebAPI -> EventQueue
aysnc最主要的作用就是:如果想在函數中使用await,則當前函數必須基于async修飾
aysnc修飾符,讓函數的返回值成為一個promise實例 這樣就可以基于THEN鏈去處理了
如果函數自己本身就返回一個promise實例,則以自己返回的為主
如果函數自己本身沒有返回promise,則會把返回值變為一個promise實例:狀態=> 成功 值=>返回值
如果函數執行報錯則返回的實例狀態是失敗,值是報錯原因,但不影響下面代碼執行
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 () {...} 函數 return result(); }).then(result => { console.log(result); //10 });
我們一般在其后面放promise實例 它會等待實例狀態為成功,再去執行“當前上下文”中 ,await下面的代碼
【如果promise實例管控的是一個異步編程,其實它是在等待異步成功,再執行下面的代碼,類似于把異步改為同步的效果】
await 10 =>默認轉為 await Promise.resolve(10)
如果后面放的不是promise實例,則瀏覽器默認把其轉換為”狀態為成功,值就是這個值 " 的實例
const fn1 = () => { return new Promise(resolve => { setTimeout(() => { resolve(1); }, 1000); }); }; (async function () { let result = await fn1(); console.log(result); //下面代碼可以執行,說明await后面的promise實例,它的狀態已經是成功了,await的返回值就是當前promise實例的值 console.log('OK'); })(); //=======================如果await后面的promise實例狀態是失敗的 const fn1 = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject(0); }, 1000); }); }; (async function () { let result = await fn1(); //如果await后面的promise實例狀態是失敗的,則下面代碼永遠都不會執行了 console.log(result); console.log('OK');//如果是失敗的則這句話不會執行 })(); //=================================================== (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下面的代碼執行是異步微任務
情況1:await后面的promise實例我們已知是成功的
先把微任務放置在WebAPI中,但是知道是可以執行的,則直接在挪至到EventQueue中等待執行
情況2:await后面的promise實例還是pending狀態
此時我們把微任務放置在WebAPI中監聽,等到后期promise實例是成功態后,再把它挪至到EventQueue中等待執行即可
(async function () { let b = await Promise.resolve(20); console.log(b); })()
console.log(1); setTimeout(() => { console.log(2); });//宏1 console.log(3); let p1 = new Promise(resolve => {//new Promise 立即會把executor函數執行 是同步 console.log(4); resolve('A'); //執行resolve P1的狀態是成功=》已知 console.log(5); }); console.log(6); p1.then(result => {//.then是異步 已知狀態 放進WebAPI中監聽 但是因為是已知狀態 方法肯定執行 則從WebAPI監聽隊列挪到EventQueue中等待 console.log(result); //微1 }); console.log(7); let p2 = new Promise(resolve => { //立即執行executor函數 setTimeout是異步則會放進WebAPI監聽 宏2 setTimeout(() => { resolve('B'); console.log(10); //執行宏2=>@1 更改了p2的狀態 @2之前存儲的.then方法執行 }); }); console.log(8); p2.then(result => {//p2的狀態是未知則會先存起來 console.log(result); }); console.log(9);
基于事件綁定屬于異步宏任務
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); });
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');
以上就是關于“JavaScript中Promise如何處理異步的并行與串行”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。