前言
近日作業上有一個需求,頁面上有一個歷史記錄的東西,存盤了最近使用的10張圖片(大概知道下背景就好,不用深究)每一次頁面重繪,ready后,要去服務器拉取那幾張圖片的URL,以便在頁面上展示,因為產品要求歷史記錄的圖片要按使用的時間順序排列展示,我想了一下,決定按順序發起【拉取圖片URL】的請求(不要問我為什么),在使用程序中碰到了問題,網友的答案我不大滿意,所以特此總結一下,
套路
處理這類問題的方法有以下兩種:
- Promise鏈式執行
- 利用async/await
我姑且認為大家的Promise是這么發出去的:
1 /** 2 * 不帶引數 3 */ 4 function p1() { 5 // ... 前置處理 6 return new Promise((resolve, reject) => { 7 // ... 業務代碼 8 9 }) 10 } 11 12 p1().then(res => { 13 // 后續處理 14 }, err => { 15 // 后續處理 16 })
1 /** 2 * 帶引數 3 */ 4 function p1(param) { 5 // ... 前置處理 6 return new Promise((resolve, reject) => { 7 // 業務代碼 8 9 }) 10 } 11 12 p1(param).then(res => { 13 // 后續處理 14 }, err => { 15 // 后續處理 16 })
接下來我將分【帶引數】和 【不帶引數】兩種情況,分別說明,
代碼
不帶引數
鏈式執行法
1 function p1() { 2 return new Promise((resolve, reject) => { 3 resolve(1); 4 }) 5 } 6 7 function p2() { 8 return new Promise((resolve, reject) => { 9 resolve(2); 10 }) 11 } 12 13 function queue(...t) { 14 // 回傳一個resolve狀態的Promise物件,方便第一次在then中呼叫異步任務 15 let _queue = Promise.resolve(); 16 let result = []; 17 t.forEach(p => { 18 _queue = _queue.then(p).then(res => { 19 result.push(res); 20 // 為了在最后一個then中獲取到結果,因為then回傳的是一個新的Promise實體 21 // 如果在外層有存盤結果的物件,這里就不用return 22 return result; 23 }); 24 }); 25 return _queue; 26 } 27 28 queue(p1, p2).then(res => { 29 console.log(res); // [1, 2] 30 })
async/await法
1 function p1() { 2 return new Promise((resolve, reject) => { 3 resolve(1); 4 }).then(() => { 5 return "ok"; 6 }) 7 } 8 9 function p2() { 10 return new Promise((resolve, reject) => { 11 resolve(2); 12 }) 13 } 14 15 async function exec() { 16 // ... 前置處理 17 let result = []; 18 console.log("執行p1") 19 let res1 = await p1(); 20 console.log("執行p2"); 21 let res2 = await p2(); 22 // ... 若干promise 23 result.push(res1, res2); 24 return Promise.resolve(result); 25 } 26 27 exec().then(res => { 28 console.log(res); // ["ok", 2] 29 }); 30 31 /** 32 * 注意:此處的代碼并不會等exec()函式執行結束后才執行 33 * 因為在exec()中執行的Promise,一經發出會立即執行,then中的處理函式進入微任務佇列,等宏任務執行完后, 34 * 再來執行微任務佇列中的所有函式,如此反復,所以此處的代碼在第一個Promise發出后,就會執行, 35 * 因為此文分享 [Promise順序執行],所以不過多談及這個,但還是提一下吧,36 */ 37 console.log("亂入");
這樣也可以:
1 function p1() { 2 return new Promise((resolve, reject) => { 3 resolve(1); 4 }).then(() => { 5 return "ok"; 6 }) 7 } 8 9 function p2() { 10 return new Promise((resolve, reject) => { 11 resolve(2); 12 }) 13 } 14 15 async function exec(...t) { 16 // ... 前置處理 17 let result = []; 18 for (let p of t) { 19 let res = await p(); 20 result.push(res); 21 } 22 return Promise.resolve(result); 23 } 24 25 exec(p1, p2).then(res => { 26 console.log(res); // ["ok", 2] 27 });
帶引數
鏈式執行法
1 function p1(id) { 2 return new Promise((resolve, reject) => { 3 resolve(id); 4 }) 5 } 6 7 function queue(ids) { 8 // ... 前置處理 9 let result = []; 10 let _queue = Promise.resolve(); 11 ids.forEach(function(id) { 12 _queue = _queue.then(() => { 13 // 只有這樣,后面那個then才可以獲取到p1的執行結果 14 return p1(id); 15 }).then(res => { 16 result.push(res); 17 return result; 18 }) 19 }) 20 return _queue; 21 } 22 23 queue([1, 2, 3]).then(res => { 24 console.log(res); // [1, 2, 3] 25 })
這樣也可以:
1 function p1(id) { 2 return new Promise((resolve, reject) => { 3 resolve(id); 4 }) 5 } 6 7 function queue(ids) { 8 // ... 前置處理 9 let result = []; 10 let _queue = Promise.resolve(); 11 ids.forEach(function(id) { 12 _queue = _queue.then(() => p1(id).then(res => { 13 result.push(res); 14 return result; 15 })); 16 }) 17 return _queue; 18 } 19 20 queue([1, 2, 3]).then(res => { 21 console.log(res); // [1, 2, 3] 22 })
async/await法
1 function p1(id) { 2 return new Promise((resolve, reject) => { 3 resolve(id); 4 }) 5 } 6 7 async function exec(...ids) { 8 // ... 前置處理 9 let result = []; 10 for (let id of ids) { 11 let res = await p1(id); 12 result.push(res); 13 } 14 return Promise.resolve(result); 15 } 16 17 exec(1, 2).then(res => { 18 console.log(res); // [1, 2] 19 });
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/134945.html
標籤:其他
上一篇:異步執行原理
