一、问题描述
在这个例子中,通过 forEach 遍历的将每一个数字都执行 multi 操作。代码执行的结果是:1 秒后,一次性输出1,4,9。这个结果和我们的预期有些区别,我们是希望每间隔 1 秒,然后依次输出 1,4,9;所以当前代码应该是并行执行了,而我们期望的应该是串行执行。 forEach 的回调函数是一个异步函数,异步函数中包含一个 await 等待 Promise 返回结果,我们期望数组元素串行执行这个异步操作,但是实际却是并行执行了。
二、怎么解决
方法一、
方法二、利用for of 代替 forEach
for of的原理
for-of 可以遍历各种集合对象的属性值,要求被遍历的对象需要实现迭代器 (iterator) 方法,例如 myObjectSymbol.iterator 用于告知 JS 引擎如何遍历该对象。一个拥有 Symbol.iterator 方法的对象被认为是可遍历的。
var zeroesForeverIterator = {
[Symbol.iterator]: function () {
return this;
},
next: function () {
return {done: false, value: 0};
}
};
如上就是一个最简单的迭代器对象;for-of 遍历对象时,先调用遍历对象的迭代器方法 Symbol.iterator,该方法返回一个迭代器对象(迭代器对象中包含一个 next 方法);然后调用该迭代器对象上的 next 方法。
每次调用 next 方法都返回一个对象,其中 done 和 value 属性用来表示遍历是否结束和当前遍历的属性值,当 done 的值为 true 时,遍历就停止了。
归纳为:
当遍历ITERABLE时,执行发生了什么?
for (VAR of ITERABLE) {
STATEMENTS
}
等价于:
var $iterator = ITERABLESymbol.iterator; // 先执行ITERABLE的迭代器方法
var $result =
i
t
e
r
a
t
o
r
.
n
e
x
t
(
)
;
/
/
执
行
n
e
x
t
(
)
方
法
w
h
i
l
e
(
!
iterator.next(); // 执行next()方法 while (!
iterator.next();//执行next()方法while(!result.done) { // 未遍历完
VAR = $result.value;
STATEMENTS
$result = $iterator.next();
}
for …of内部next()相当于一个手动同步开关,一步一步的执行STATEMENTS。
所以,可以写成这样