简体   繁体   English

异步等待多个setIntervals

[英]async await with multiple setIntervals

I have two API requests, one that gets called every 5000ms and one that gets called every 30000ms. 我有两个API请求,一个每5000毫秒调用一次,一个每30000毫秒调用一次。 I want to ensure that each call is completed before issuing a new request to the server. 我要确保在向服务器发出新请求之前完成每个调用。 I don't want either of the requests to overlap one another. 我不希望任何一个请求都相互重叠。 For example, if func1 API hasn't completed then I don't want to issue func2 API call until that one completes. 例如,如果func1 API尚未完成,那么在该函数完成之前,我不希望发出func2 API调用。

This is what I've tried so far. 到目前为止,这是我尝试过的。

async function vals() {
            try {
                await func1()
                    .then(response => response.json())
                    .then(result => display_result(result))
                    .catch(error => console.error('Error: ', error));
                await func2()
                    .then(response => response.json())
                    .then(result => display_result(result))
                    .catch(error => console.error('Error: ', error));
            }
            catch(error) {
                return error;
            }
}

vals();

Here are func1 and func2. 这是func1和func2。

function func1() {
        return setInterval(() => fetch(url, { method: 'GET' }), 5000);
}

function func2() {
        return setInterval(() => fetch(url, { method: 'GET' }), 30000);
}

I would expect this to run func1() first, wait for it to resolve, and then run func2(). 我希望它先运行func1(),等待它解决,然后再运行func2()。 Instead func1() gets called twice and never gets to func2(). 相反,func1()被调用两次,并且从不访问func2()。 Should the setIntervals be set inside the vals() function instead? 应该将setIntervals设置在vals()函数内部吗? Any guidance to make this work would be much appreciated. 任何指导,使这项工作将不胜感激。

Ok this is a bit tricky! 好的,这有点棘手! You have two different intervals spawning tasks (http requests) which take a non-trivial amount of time, and you want to make sure that the tasks don't coincide with each other. 您有两个不同的时间间隔生成任务(http请求),它们花费的时间很短,并且您要确保任务彼此不重合。

I recommend that instead of immediately activating your requests in the timeout, instead add the requests to a queue of work-to-be-done. 我建议不要在超时中立即激活您的请求,而应将请求添加到待完成的工作队列中。 That queue will process a number of tasks in serial as quickly as it can. 该队列将尽可能快地串行处理许多任务。

 // In your example your "long-running-tasks" are http requests. // In this example I'll use a timeout. let genLongRunningTask1 = async () => { console.log('Task 1 start'); await new Promise(r => setTimeout(r, 1500)); console.log('Task 1 end'); }; let genLongRunningTask2 = async () => { console.log('Task 2 start'); await new Promise(r => setTimeout(r, 1600)); console.log('Task 2 end'); }; // The tail of the promise-queue. If it resolves we're ready // to begin a new long-running-task. It's initially resolved. let queueTail = Promise.resolve(); let queueNewTask = async genLongRunningTask => { await queueTail; await genLongRunningTask(); }; // Now setup our intervals. We don't directly generate any // long-running-tasks here - instead we "queue" them, and // then point the tail of the queue to their completion. console.log('Starting...'); setInterval(() => { queueTail = queueNewTask(genLongRunningTask1); }, 3000); setInterval(() => { queueTail = queueNewTask(genLongRunningTask2); }, 6000); 

In my example the two intervals are at 3000ms and 6000ms , so they should run simultaneously every 6000ms - but you'll see that the queueing logic keeps them nice and separate! 在我的示例中,两个间隔分别为3000ms6000ms ,因此它们应该每6000ms同时运行一次-但您会看到排队逻辑使它们保持良好和独立状态! You'll never see a new task start before the previous task has ended. 在上一个任务结束之前,您将永远不会看到新任务开始。

In your case you should only need to edit genLongRunningTask1 and genLongRunningTask2 so that they await and process your request. 在您的情况下,您只需要编辑genLongRunningTask1genLongRunningTask2以便它们等待并处理您的请求。 Something like the following: 类似于以下内容:

 let genLongRunningTask1 = async () => { try { // Assuming `func1` returns a "response object": let response = await func1(); /* Assuming the "response object" has a `json` method, and `display_result` is an async method for showing the json data. NOTE: this use of `await` ensures requests will remain queued until the previous request is done processing *and* rendering. To begin sending the next request after the previous request has returned, but overlapping with the period in which that request is still *rendering*, omit `async` here. */ await display_result(response.json()); } catch(err) { console.error('Error:', err); } }; 

Warning: Be careful that you aren't queuing tasks more quickly than the tasks can complete! 警告:请注意,排队任务的速度不会比完成任务的速度快!

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

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