字节:输出以下代码运行结果,为什么?如果希望每隔 1s 输出一个结果,应该如何改造?注意不可改动 square 方法
sisterAn opened this issue · comments
const list = [1, 2, 3]
const square = num => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * num)
}, 1000)
})
}
function test() {
list.forEach(async x=> {
const res = await square(x)
console.log(res)
})
}
test()
1s
后同时打印 1、4、9
原因:使用 promise
或 async
函数作为 forEach()
等类似方法的 callback
参数并不会等待异步的执行
如果我们希望每隔 1s
输出一个结果,方法有:
- 一个简单的
for
循环 for…of
/for…in
循环- 利用
promise
的链式调用
解法一:for 循环
async function test() {
for(let i = 0; i<list.length; i++) {
const res = await square(list[i])
console.log(res)
}
}
test()
解法二:for…in / for…of
for...in
async function test() {
for(let i in list) {
const res = await square(list[i])
console.log(res)
}
}
test()
for...of
async function test() {
for(let x of list) {
const res = await square(x)
console.log(res)
}
}
test()
解法三:利用 promise 的链式调用
function test() {
let promise = Promise.resolve()
list.forEach(x=> {
promise = promise.then(() => square(x)).then(console.log)
})
}
test()
运行结果:一秒后输出1,4,9
原因:在forEach里面写的callback函数会直接在while循环里面调用
改造:用for...of 或者for循环代替 forEach
async function test () {
for(let x of list) {
var res = await square(x)
console.log(res)
}
}
贴一下forEach的源码
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback, thisArg) {
var T, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
if (typeof callback !== "function") {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = thisArg;
}
k = 0;
while (k < len) {
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
}
k++;
}
};
}
运行结果,直接输出1 4 9
原因:是同步代码,直接执行了
代码:
async function test() {
for await (const x of list) {
const res =await square(x)
console.log(res)
}
}
test()
遍历异步的循环
运行结果,直接输出1 4 9
原因:用了递归调用
代码:
const list = [1, 2, 3]
const square = num => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * num)
}, 1000)
})
}
async function test(index = 0) {
const res = await square(list[index])
console.log(res)
if (list[++index]) {
test(index)
}
}
test()
const list = [1, 2, 3];
const square = (num) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(num * num);
}, 1000);
});
};
function test() {
list.forEach(async (x) => {
const res = await square(x);
console.log(res);
});
}
test();
function test2() {
let p = Promise.resolve();
for (const item of list) {
p = p.then(() => square(item).then(console.log));
}
}
test2();
async function test3() {
for (const item of list) {
const res = await square(item);
console.log(res);
}
}
test3();
function test4() {
class Schedule {
constructor() {
this.list = [];
this.status = "waiting";
}
add(fn) {
this.list.push(fn);
if (this.status === "waiting") {
this.run();
}
}
async run() {
this.status = "running";
while (this.list.length) {
const task = this.list.shift();
await task();
}
this.status = "waiting";
}
}
const schedule = new Schedule();
for (const item of list) {
schedule.add(() => square(item).then(console.log));
}
}
test4();