Javascript 按顺序解决承诺

Javascript 按顺序解决承诺,javascript,asynchronous,promise,Javascript,Asynchronous,Promise,编辑:这是一个Electron项目,用户系统上有一个本地服务器。因此,如果多个用户同时尝试访问,那么任何关于会发生什么的问题都可以忽略 我的客户端代码正在生成一个JavaScript对象数组,我正在调用它。虽然1到10之间是最常见的用例,但可能存在无限的数据包 我需要对后端路由进行API调用,每个数据包一个,将数据包作为参数传递给每个调用 但是,后端会对每个数据包执行一些繁重的计算工作,如果试图一次处理2-3个以上的数据包,服务器就会崩溃 是否有可能同步解析承诺,使得第二个承诺仅在第一个承诺解

编辑:这是一个Electron项目,用户系统上有一个本地服务器。因此,如果多个用户同时尝试访问,那么任何关于会发生什么的问题都可以忽略


我的客户端代码正在生成一个JavaScript对象数组,我正在调用它。虽然1到10之间是最常见的用例,但可能存在无限的数据包

我需要对后端路由进行API调用,每个数据包一个,将数据包作为参数传递给每个调用

但是,后端会对每个数据包执行一些繁重的计算工作,如果试图一次处理2-3个以上的数据包,服务器就会崩溃

是否有可能同步解析承诺,使得第二个承诺仅在第一个承诺解析时触发,第三个承诺在第二个承诺解析后触发,依此类推

我的理解是,Promise.all()同时进行所有调用,这对我没有帮助

(我也知道这是一种反模式,但对于我的特定需求集,我不确定还能做什么)

我知道这纯粹是抽象的,但任何想法都会被欣赏

对承诺感到奇怪 异步队列,是我的一个分支;我添加了随机完成时间来模拟真实环境:

类队列{
构造函数(){
this.queue=[];
}
排队(obj){
返回此.queue.push(obj);
}
出列(){
返回此.queue.shift();
}
hasWork(){
返回(this.queue.length>0);
}
}
类AsyncQueue扩展队列{
建造师(工作){
超级();
这个工作=工作;
}
过程(cb){
返回this.job(this.dequeue())。然后(data=>{
cb(数据);
if(this.hasWork())
返回此进程(cb);
});
}
}
//必须回报承诺
职能工作(){
var duration=chooseDelay();
console.log('START JOB,即发出请求(需要%s)',持续时间);
返回t_o(持续时间);
}
功能报告(){
console.log('JOB DONE');
}
函数完成(){
console.log(“所有已完成的工作”);
}
功能t_o(延迟){
返回新承诺(功能(解决、拒绝){
setTimeout(函数(){
解决();
},延误);
});
}
函数选择延迟(){
var延迟=[20010004000100507000];
返回延迟[parseInt(Math.random()*100)%delays.length];
}
var q=新的异步队列(工作);
用于(var数据包=0;数据包<10;++数据包)
q、 排队(分组);

q、 过程(报告)。然后(完成)
作为一个好答案的替代方案,这里有一个非常简单的队列可以工作(
work
函数无耻地从其他答案复制和扩展)

//这是队列“创建者”
让允诺者排队=fn=>{
让q=Promise.resolve();
返回(…args)=>q=q,然后(()=>fn(…args));
};
//这就是承诺队列的全部代码
//这里我们创建一个队列
var q=承诺队列(工作);
//简单模拟异步函数
函数工作({index,data}){
var duration=parseInt(Math.random()*100)+100;
console.log('启动作业%s,即发出请求(需要%s),结果应为%s',索引,持续时间,(索引+1)*数据);
返回新承诺(resolve=>setTimeout(resolve,duration))//模拟延迟
.然后(()=>({index,result:(index+1)*data}));//和一些“处理”
}
//模拟两个“块”数据包,生成间隔为毫秒,但序列仍将保持不变
设置超时(()=>{
var packets=Array.from({length:10},({index,index)=>({index,data:parseInt(Math.random()*10000)});
var promises=packets.map(packet=>q(packet));
//promise all中的结果都是这批“数据包”的结果
然后(results=>console.log(results));
}, 100);
设置超时(()=>{
var packets=Array.from({length:10},({index:index+10,data:parseInt(Math.random()*10000)});
var promises=packets.map(packet=>q(packet));
然后(results=>console.log(results));

}, 101);按顺序执行的简单函数

const sequentiallyExecuting = (promises) => {
    let promise = Promise.resolve();
    promises.forEach((task) => {
        promise = promise.then((data) => {
            return task;
        })
    });

    return promise;
}
// pass array of promises to this function
sequentiallyExecuting(promises).then((data) =>{
   console.log("all requests completed sequentially");
})
“严格使用”;
//要做的工作
功能作业(参数){
返回函数(){
console.log('作业已启动',参数);
返回新承诺(函数(解析){
setTimeout(函数(){
console.log('job finished');
解决();
}, 1000);
})
}
}
//要按顺序处理的数据
变量参数=[
1.
2.
3.
4.
5.
];
//将数据简化为承诺序列
参数减少(功能(cum,cur){
返回兼当时(工作(当前));

},Promise.resolve())使用async/await它变得微不足道:

while (promiseArray.length > 0)
        await promiseArray.shift();

是的,“顺序”会更好。我的意思是承诺1需要在承诺2开始之前完成,承诺2需要在承诺3开始之前完成,依此类推,直到承诺N。
我的客户端代码正在生成一个JavaScript对象数组
-让我问这个问题。您是否正在创建数组,并且一旦生成了数组,就进行API调用?或者更像是这样一种情况,即这些对象是动态创建的,并且您希望确保一次只调用一个API,即下面的“队列”答案将是您刚才描述的理想声音。使用。一种选择是将其视为where
n=1
,尽管听起来您对
n=2
n=3
也很满意。很有趣!我来试试,然后回去报告!这真是太好了。类和助手函数的大量使用,非常清晰。您可以通过将
this.job()
调用包装为
promise.resolve()
,来解决不返回承诺的问题,但这可能不是您希望静默允许的,因为它可能表示类似遗忘的错误