简体   繁体   English

顺序解决承诺

[英]resolving Promises sequentially

EDIT: This is for an Electron project, with a local server spun up on the user's system. 编辑:这是针对Electron项目的,在用户系统上启动了本地服务器。 So, any concerns about what happens if multiple users attempt simultaneous access can be ignored! 因此,对于如果多个用户尝试同时访问会发生什么的任何担忧都可以忽略!


My client code is generating an array of JavaScript objects, which I'm calling packets . 我的客户代码正在生成一个JavaScript对象数组,我将其称为packets There can be potentially infinite packets , although between 1 and 10 is the most common use-case. 尽管最常见的用例是在1到10之间,但可能存在无限的数据包

I need to make API calls to a backend route, one per packet , passing a packet as an argument to each call. 我需要对后端路由进行API调用,每个数据包一个,将数据包作为参数传递给每个调用。

However, the backend does some heavy computational work on each packet , to the point where attempting to crunch more than 2-3 packets at once crashes the server. 但是,后端会对每个数据包执行一些繁重的计算工作,以至于试图一次处理超过2-3个数据包会使服务器崩溃。

Is it possible to resolve Promises synchronously, such that the second Promise only fires when the first resolves, the third firing after the second, and so on? 是否可以同步解决的承诺 ,使得第二承诺仅火灾时,第一个做出决议,第二个之后的第三射击,等等?

It's my understanding that Promise.all() makes all calls simultaneously, which doesn't help me here. 据我了解, Promise.all()同时进行所有调用,这对我没有帮助。

(I also know that this is an anti-pattern, but for my specific set of requirements, I'm not sure what else to do) (我也知道这是一个反模式,但是对于我的特定要求,我不确定该怎么做)

I know this is purely abstract, but any thoughts would be appreciated!!! 我知道这纯粹是抽象的,但是任何想法都将不胜感激!!!

Get weird with Promises 对承诺感到奇怪

An async queue, a spin-off one of my previous answers ; 一个异步队列,是我以前的回答中的一个 I've added random completion time to simulate a real environment: 我添加了随机完成时间来模拟真实环境:

 class Queue { constructor() { this.queue = []; } enqueue(obj) { return this.queue.push(obj); } dequeue() { return this.queue.shift(); } hasWork() { return (this.queue.length > 0); } } class AsyncQueue extends Queue { constructor(job) { super(); this.job = job; } process(cb) { return this.job(this.dequeue()).then(data => { cb(data); if (this.hasWork()) return this.process(cb); }); } } //MUST RETURN Promise function work() { var duration = chooseDelay(); console.log('START JOB, IE, MAKE REQUEST (will take %s)', duration); return t_o(duration); } function report() { console.log('JOB DONE'); } function done() { console.log('ALL WORK DONE'); } function t_o(delay) { return new Promise(function (resolve, reject) { setTimeout(function () { resolve(); }, delay); }); } function chooseDelay() { var delays = [200, 1000, 4000, 100, 50, 7000]; return delays[parseInt(Math.random() * 100) % delays.length]; } var q = new AsyncQueue(work); for (var packet = 0; packet < 10; ++packet) q.enqueue(packet); q.process(report).then(done); 

As an alternative to an otherwise good answer, here's a really simple queue that works ( work function shamelessly copied and expanded from other answer) 作为一个很好的答案的替代方法,这是一个非常简单的队列,可以正常工作( work函数从其他答案中无耻地复制和扩展)

  // Here is the queue "creator" let promiseQueue = fn => { let q = Promise.resolve(); return (...args) => q = q.then(() => fn(...args)); }; // that's it, that's the whole code for a promise queue // here we create a queue var q = promiseQueue(work); // simple mock asynchronous function function work({index, data}) { var duration = parseInt(Math.random() * 100) + 100; console.log('START JOB %s, IE, MAKE REQUEST (will take %s) and should result with %s', index, duration, (index +1) * data); return new Promise(resolve => setTimeout(resolve, duration)) // mock a delay .then(() => ({index, result:(index + 1) * data})); // and some "processing" } // simulating two "chunks" of packets, generated a millisecond apart, but still, the sequence will be maintained setTimeout(() => { var packets = Array.from({length:10}, (_, index) => ({index, data:parseInt(Math.random() * 10000)})); var promises = packets.map(packet => q(packet)); // the results in promise all are all the results of this batch of "packets" Promise.all(promises).then(results => console.log(results)); }, 100); setTimeout(() => { var packets = Array.from({length:10}, (_, index) => ({index: index + 10, data:parseInt(Math.random() * 10000)})); var promises = packets.map(packet => q(packet)); Promise.all(promises).then(results => console.log(results)); }, 101); 

the simple function to execute promises sequentially 依次执行promise的简单功能

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");
})

 'use strict'; // job to be done function job(params) { return function () { console.log('job started', params); return new Promise(function (resolve) { setTimeout(function () { console.log('job finished'); resolve(); }, 1000); }) } } // data to be processed sequentially var params = [ 1, 2, 3, 4, 5 ]; // reduce data to Promise sequence params.reduce(function (cum, cur) { return cum.then(job(cur)); }, Promise.resolve()); 

With async/await it becomes trivial: 使用async / await变得微不足道:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM