在下面的示例中,我希望在几秒钟后解析数组的每个元素。它现在的表现如何在4秒后解决Promise,我希望它能在16秒后解决因为有4个元素。
const numbers = [1, 2, 3, 4];
const promises = numbers.map(number => {
return new Promise(resolve => {
setTimeout(() => {
console.log(number);
resolve(number);
}, 4000);
});
});
Promise.all(promises).then( () => {
console.log("Done");
});
答案 0 :(得分:3)
使用新的Async / Await,现在已经广泛实施了。如果没有,您可以转换旧浏览器。
您可以创建更加线性且更容易理解的代码。
值得一提的是,bluebird有一个基于promise的映射,它具有一个并发选项,非常适合映射位。
const numbers = [1, 2, 3, 4];
async function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
//pretend show number async
async function showNumber(l) {
return new Promise((resolve) => {
setTimeout(() => { console.log(numbers[l]); resolve(); });
});
}
async function doNumbers() {
for (let l = 0; l < numbers.length; l ++) {
await delay(4000);
await showNumber(l);
}
console.log("Done");
}
doNumbers();
答案 1 :(得分:2)
这是正常的行为,因为Promise是异步的并且实际上是并发的。 Promise.all只是等待所有的promises完成,它不是一个在另一个之后调用promise的精化队列。如果你想一个接一个地执行操作,只是不使用promises,使用正常的同步周期:)
答案 2 :(得分:1)
它将所有值传递给map函数,然后迭代它们并为它们创建异步工作4秒。它不会在彼此之后调用setTimeout
。
您的4秒仅与setTimeout
的回调有关,而与map
功能无关,这意味着将至少在4秒后调用回叫。因此引擎为setTimeout
创建了不同的线程,并在4秒后调用它。当另一个线程中的第一个时间流逝时,在JS线程中它传递第二个值并为每个项目执行相同的操作。
可以使用RxJS
完成一个解决方案
Rx.Observable.from([1,2,3,4]).map(value => Rx.Observable.of(value).delay(4000)).concatAll().subscribe(x => console.log(x));
&#13;
<script src='https://unpkg.com/@reactivex/rxjs@5.4.3/dist/global/Rx.js'></script>
&#13;
答案 3 :(得分:1)
每次增加您的计时器,乘以number
:
const numbers = [1, 2, 3, 4];
const promises = numbers.map(number => {
return new Promise(resolve => {
setTimeout(() => {
console.log(number);
resolve(number);
}, number*4000);
});
});
Promise.all(promises).then( () => {
console.log("Done");
});
16秒后显示“完成”。
答案 4 :(得分:1)
创建承诺时,超时将设置为4秒,并在~4秒后同时到期。 要实现所需的行为,您可以执行以下操作:
const numbers = [1, 2, 3, 4];
const promises = numbers.map((number, i) => {
return new Promise(resolve => {
setTimeout(() => {
console.log(number);
resolve(number);
}, 4000*(i+1));
});
});
Promise.all(promises).then( () => {
console.log("Done");
});
答案 5 :(得分:0)
如果您需要按顺序运行每个承诺,而不是并行运行。 你可以使用异步函数,然后等待继续使用promises。 对于无异步功能解决方案,您可以使用此功能较旧的解决方案。使用数组reduce方法。请注意我正在生成一系列函数,每个函数都会返回一个promise。
const numbers = [1, 2, 3, 4];
numbers.map(number => () => {
return new Promise(resolve => {
setTimeout(() => {
console.log(number);
resolve(number);
}, 4000);
});
}).reduce(
(promise, asyncJob) => promise.then(() => asyncJob()),
Promise.resolve()
).then(() => { console.log('done'); });