js中遍历执行异步操作


遇到个遍历执行异步操作的场景,习惯性地去用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里得到所有接口的结果

我的微信公众号: 梨的前端小屋


文章作者: 梨啊梨
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 梨啊梨 !
  目录