遇到个遍历执行异步操作的场景,习惯性地去用forEach去执行操作,发现并不是自己想要的结果,因为循环很快就会完成,那这样的话就用Promise去做。
在 js 中,可以使用 for
循环遍历数组或对象并执行异步操作。但是,由于异步操作不会阻塞主线程,循环会立即执行完毕,而异步操作的结果可能需要一定时间才能返回,因此需要使用回调函数或者 Promise 来处理异步操作的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| function asyncOperation(item) { return new Promise(resolve => { setTimeout(() => { resolve(item + Math.random() * 1000); }, 5000); }); }
// 定义一个数组 const array = [1, 2, 3];
// 使用 async/await 进行循环遍历 async function loop() { const arr = []; for (const item of array) { const result = await asyncOperation(item); arr.push(result) } console.log(arr); // 当异步全部完成后,才会打印出结果 }
// 调用 loop 函数 loop();
|
在上面的代码中,asyncOperation
函数是一个异步函数,它会返回一个 Promise 对象。在 loop
函数中,我们使用 for of
循环遍历数组,并在每次循环中使用 await
等待异步操作的结果返回。由于 await
会使得循环暂停等待异步操作的结果,因此可以保证异步操作的顺序执行。这样就达到了我想要的结果。
再来一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const handleQuery = async(url) => { try { const res = await fetch(url); const data = await res.json(); return data.id; } catch (e) { console.log(e); } }
export const initData = async() => { const baseUrl = "https://jsonplaceholder.typicode.com/todos"; const resultList = []; // 结果 for (let i = 1; i < 10; i++) { try { const result = await handleQuery(`${baseUrl}/${i}`); resultList.push(result); } catch (error) { // 处理单个请求错误,如果你需要在这里处理错误 console.error(`Error in request ${i}:`, error); } } console.log(resultList); // [1,2,3,4,5,6,7,8,9] } initData(); 这样当我们执行的时候,9个请求会依次请求,最终的结果会存在resultList里
|
如果需要并行执行异步操作,可以使用 Promise.all 方法来等待所有异步操作完成。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| // 定义一个异步函数 function asyncOperation(item) { return new Promise(resolve => { setTimeout(() => { console.log(item); resolve(); }, 5000); }); }
// 定义一个数组 const array = [1, 2, 3];
// 使用 Promise.all 进行并行执行 Promise.all(array.map(item => asyncOperation(item))).then(() => { console.log('all done'); });
|
在上面的代码中,我们使用 Promise.all
方法来等待所有异步操作完成。Promise.all
方法会接收一个 Promise 数组作为参数,并在所有 Promise 对象都成功执行后返回一个新的 Promise 对象。在本例中,我们使用 array.map
方法将数组中的每个元素都传递给 asyncOperation
函数并返回一个 Promise 数组,然后使用 Promise.all
方法等待所有异步操作完成
再来一个例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| const handleQuery = async(url) => { try { const res = await fetch(url); const data = await res.json(); return data.id; } catch (e) { console.log(e); } }
export const initData = async() => { const baseUrl = "https://jsonplaceholder.typicode.com/todos"; const requestList = []; for (let i = 1; i < 10; i++) { const request = handleQuery(`${baseUrl}/${i}`); requestList.push(request); // 请求列表存起来 } try { const res = await Promise.all(requestList); // 接口同时全部请求 console.log(res); // [1,2,3,4,5,6,7,8,9] } catch (e) { console.log(e); } } initData(); 这样当我们执行initData的时候,他会把9个请求同时发出去,并且在res里得到所有接口的结果
|
我的微信公众号: 梨的前端小屋