如果响应为running
,我需要每2秒调用一次api,并在响应为complete
或failed
或直到30秒过去时首先返回并且该功能超时。
这是我现在可以使用的功能,但是我确信它可以更高效地完成工作,但是我现在还无法弄清楚:
const getStatus = async (processId) => {
try {
const response = await fetch(`example.com/api/getStatus/${processId}`);
const status = await response.json();
return await status;
} catch(err) {
// handle error
}
}
使用getStatus()在另一个异步函数中:
randomFunction = async () => {
let status = null;
let tries = 0;
let stop = false;
while (tries <= 15 && !stop) {
try {
status = await getStatus('some-process-id');
if (status === 'complete') {
stop = true;
// do something outside of loop
}
if (status === 'failed') {
stop = true;
throw Error(status);
}
if (tries === 15) {
stop = true;
throw Error('Request timed out');
}
} catch (err) {
// handle error
}
const delay = time => new Promise(resolve => setTimeout(() => resolve(), time));
if (tries < 15) {
await delay(2000);
}
tries++;
}
}
我希望以更易读的格式处理getStatus()
内部的循环,但是有可能吗?
编辑: 我尝试了一种看起来更好并且似乎可以按预期工作的解决方案,请在此处查看:
https://gist.github.com/AntonBramsen/6cec0faade032dfa3c175b7d291e07bd
让我知道解决方案的某些部分是否包含任何不好的解决方案。
答案 0 :(得分:0)
您的问题是关于javascript的。不幸的是我不喝咖啡,我只能给你C#中的代码。但是我想您已经精髓了,可以弄清楚如何将其翻译成Java
让我们将其作为通用函数来实现:
您有一个每个TimeSpan
都被调用的函数,并且您希望在该函数返回true
时停止调用该函数,而您要在经过某个最大时间后取消该函数。
在这个最长的时间内,我使用CancellationToken
,这使您可以取消超时,原因更多。例如,因为操作员想要关闭程序。
TapiResult CallApi<TapiResult> <Func<TapiResult> apiCall,
Func<TapiResult, bool> stopCriterion,
CancellationToken cancellationToken)
{
TapiResult apiResult = apiCall;
while (!stopCriterion(apiResult))
{
cancellationToken.ThrowIfCancellationRequested();
Task.Delay(delayTime, cancellationToken).Wait;
apiResult = apiCall;
}
return apiResult;
}
ApiCall
是要调用的Api函数。返回值为TApiResult
。在您的情况下,status
是您的TApiResult
status
等于complete
或failed
CancellationToken
是您可以从Token
获得的CancellationTokenSource
。每当您希望过程停止处理时,只需告诉CancellationTokenSource
,函数就会以CancellationException
停止假设这是您的Api:
Status MyApiCall(int x, string y) {...}
那么用法是:
Timespan maxProcessTime = TimeSpan.FromSeconds(45);
var cancellationTokenSource = new CancellationTokenSource();
// tell the cancellationTokenSource to stop processing afer maxProcessTime:
cancellationTokenSource.CancelAfter(maxProcessTime);
// Start processing
Status resultAfterProcessing = CallApi<Status>(
() => MyApiCall (3, "Hello World!"), // The Api function to call repeatedly
// it returns a Status
(status) => status == complete // stop criterion: becomes true
|| status == failed, // when status complete or failed
cancellationTokenSource.Token); // get a token from the token source
待办事项:为CancellationException添加try / catch,并处理任务取消后应执行的操作
该函数将在stopCriterion变为true时或在CancellationTokenSource取消时停止。此操作将在maxTimeOut
之后自动完成。但是,如果您想更早停止,例如因为要停止程序,就可以:
cancellationTokenSource.Cancel();