Javascript 解析承诺。包含承诺数组且超时的所有承诺
在下面的示例中,我想在几秒钟后解析数组的每个元素。它现在的行为是,它将在4秒后解决承诺,我希望它在16秒后解决,因为有4个元素Javascript 解析承诺。包含承诺数组且超时的所有承诺,javascript,promise,Javascript,Promise,在下面的示例中,我想在几秒钟后解析数组的每个元素。它现在的行为是,它将在4秒后解决承诺,我希望它在16秒后解决,因为有4个元素 const numbers = [1, 2, 3, 4]; const promises = numbers.map(number => { return new Promise(resolve => { setTimeout(() => { console.log(number);
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");
});
它将所有值传递给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))代码>
这是正常的行为,因为承诺是异步的,实际上是并发的。所有的承诺都只是等待所有的承诺完成,它不是一个精化队列,一个接一个地调用一个承诺。如果您想一个接一个地执行操作,只是不使用承诺,请使用正常的同步周期:)每次递增计时器,将其乘以数字:
const number=[1,2,3,4];
const promises=numbers.map(number=>{
返回新承诺(解决=>{
设置超时(()=>{
控制台日志(编号);
决议(编号);
},数目*4000);
});
});
承诺。所有(承诺)。然后(()=>{
控制台日志(“完成”);
});代码>当您创建承诺时,超时将设置为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");
});
使用新的Async/Await,现在已经广泛实现了这一点。如果没有,您可以为旧浏览器进行传输
您可以创建代码,这样更线性,更容易理解
还值得一提的是,bluebird有一个基于承诺的映射,它有一个并发选项,非常适合映射位
const number=[1,2,3,4];
异步函数延迟(毫秒){
返回新承诺((解决)=>{
设置超时(解析,毫秒);
});
}
//假装显示数字异步
异步函数showNumber(l){
返回新承诺((解决)=>{
setTimeout(()=>{console.log(数字[l]);resolve();});
});
}
异步函数doNumbers(){
for(设l=0;l doNumbers()代码>如果您需要按顺序而不是并行运行每个承诺。
您可以使用异步函数,然后依次使用等待。
对于非异步函数解决方案,可以使用此功能性较旧的解决方案。使用数组归约方法。注意,我正在生成一个函数数组,每个函数都返回一个承诺
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'); });
谢谢您的回复,但我正在寻找解决方案,我该怎么做?请参阅编辑后的答案。使用simplesetTimeout
有点困难,如果您不想增加延迟时间,谢谢您的回答,我认为这是最优雅的方式。回答不错,但行为与预期略有不同。第一次showNumber调用立即发生(应该延迟),并且“完成”打印在最后一次showNumber调用后4秒发生。您应该交换这两行:等待延迟(4000);等待显示编号(l)@RogerC,是的。。说得好。我将交换它们以与OP保持一致。