JavaScript 實作異步任務回圈順序執行
需求場景:陣列的元素作為異步任務的引數,回圈遍歷該陣列,并執行異步任務,
一、錯誤的實作
簡單的錯誤實作
// 異步任務的引數陣列
const arr = [1, 2, 3, 4];
// 異步任務函式
function task(params, callback) {
setTimeout(() => {
if (!!callback) {
callback(params);
}
}, 1000);
}
// 回圈遍歷異步任務的引數陣列,并執行異步任務
console.time("Test code");
arr.forEach((item, index) => {
task(item, (ret) => {
console.log("ret", ret);
console.timeEnd("Test code");
if (index + 1 < arr.length) {
console.time("Test code");
}
});
});
執行結果輸出:

由上圖可知,只有在執行第一次異步任務時耗時近 1 秒,其它異步任務執行時間遠遠達不到 1 秒,導致該問題的原因有待進一步深入研究,
使用 Promise.all 的錯誤實作
// 異步任務的引數陣列
const arr = [1, 2, 3, 4];
// 異步任務函式
function task(params, callback) {
setTimeout(() => {
if (!!callback) {
callback(params);
}
}, 1000);
}
const tasks = [];
// 回圈遍歷異步任務的引數陣列,并執行異步任務
console.time("Test code");
arr.forEach((item, index) => {
tasks.push(
new Promise((resolve) => {
task(item, (ret) => {
console.log("ret", ret);
console.timeEnd("Test code");
if (index + 1 < arr.length) {
console.time("Test code");
}
resolve(ret);
});
})
);
});
Promise.all(tasks)
.then((values) => {
console.log(values);
})
.catch((error) => {
console.error(error);
});
執行結果輸出:

由上圖可知,該種實作方式的結果和第一種方式差不多,也是只有在執行第一次異步任務時耗時 1 秒左右,剩下的異步任務執行時間達不到 1 秒,同樣,該問題也需要對其深層的原因進行研究,
二、正確的實作
// 異步任務的引數陣列
const arr = [1, 2, 3, 4];
// 異步任務函式
function task(params, callback) {
setTimeout(() => {
if (!!callback) {
callback(params);
}
}, 1000);
}
const tasks = [];
console.time("Test code");
arr.forEach((item, index) => {
tasks.push(function () {
return new Promise((resolve) => {
task(item, (ret) => {
console.log("ret", ret);
console.timeEnd("Test code");
if (index + 1 < arr.length) {
console.time("Test code");
}
resolve(ret);
});
});
});
});
// 定義一個遞回函式來依次執行任務
function runTasks(index) {
if (index >= tasks.length) {
// 如果所有任務都已經執行完畢,回傳一個 resolved 的 Promise
return Promise.resolve();
}
// 執行當前任務,然后遞回執行下一個任務
return tasks[index]().then(function () {
return runTasks(index + 1);
});
}
// 呼叫遞回函式來執行任務
runTasks(0)
.then(function () {
console.log("All tasks are done!");
})
.catch(function (error) {
console.error(error);
});
執行結果輸出:

作者:飛仔FeiZai
出處:https://www.cnblogs.com/yuzhihui/p/17222521.html
宣告:歡迎任何形式的轉載,但請務必注明出處!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/547111.html
標籤:JavaScript
上一篇:前端設計模式——迭代器模式
