我有一个承诺竞赛实现超时。我想在超时的情况下记录超时错误。
问题在于,即使获取成功,它也会记录日志,因为它并行运行,并且在超时后仍然执行。
将errorLogger.info(message)
放置在何处,以便在non-timeout
情况下不被执行?我想我把它放错了,所以它在实际拒绝之前就输出了。
return Promise.race([
fetch(url, options)
.then(function (response) {
if (response.status >= 400) {
const message = `fetch-utility.js: bad server response while fetching url=${url} with options=${options}.`;
errorLogger.error(`${message} Response: status=${response.status} statusText:${response.statusText}.`);
throw new BadServerResponseException(message, response.status);
}
return response;
}),
new Promise((_, reject) =>
setTimeout(() => {
const message = `fetch-utility.js: timeout happened while fetching details url=${url} with options=${options}.
The timeout set is ${timeout}.`;
// TODO: this gets logged even the parallel wins - need to see better way to log this
// errorLogger.error(message);
reject(new TimeoutException(message));
}, timeout),
),
]);
答案 0 :(得分:2)
将超时逻辑与您的实际业务逻辑混合是不明智的。您应该抽象出超时逻辑,这将允许您执行以下操作:
function timeoutPromise(timeout) {
return new Promise(res => setTimeout(res, timeout));
}
function withTimeout(timeout, promise, timeoutMessage) {
let done = false;
return Promise.race([
Promise.resolve(promise)
.finally(() => { done = true }),
timeoutPromise(timeout)
.then(() => {
if (!done) {
const message = timeoutMessage || `Timeout after ${timeout} ms`;
errorLogger.error(message);
throw new TimeoutException(message);
}
})
]);
}
const timeout = 12345;
function performFetch(url, options) {
return fetch(url, options)
.then(function (response) {
if (response.status >= 400) {
const message = `fetch-utility.js: bad server response while fetching url=${url} with options=${options}.`;
errorLogger.error(`${message} Response: status=${response.status} statusText:${response.statusText}.`);
throw new BadServerResponseException(message, response.status);
}
return response;
});
}
withTimeout(
timeout,
performFetch(url, options),
`fetch-utility.js: timeout happened while fetching details url=${url} with options=${options}. The timeout set is ${timeout}.`
)
答案 1 :(得分:2)
您不应将错误记录在这两个构造中,因为这样的确会始终调用它。
相反,您可以根据then
返回的诺言将catch
和Promise.race
链接起来。因此,您将使race
的参数保持很小,并将逻辑移到外部。
类似的东西:
return Promise.race([
fetch(url, options),
new Promise((_, reject) => setTimeout(() => reject("timeout"), timeout))
]).catch(function(error) {
if (error === "timeout") {
const message = "timeout happened";
errorLogger.error(message);
throw new TimeoutException(message);
} else {
const message = "fetch failed";
errorLogger.error(message);
throw new FetchException(message);
}
}).then(function (response) {
if (response.status >= 400) {
const message = "bad response";
errorLogger.error(message);
throw new BadServerResponseException(message, response.status);
}
return response; // Success within timeout!
});
答案 2 :(得分:0)
我不确定我是否100%理解您的问题,但是如果您想“取消”承诺,如果退货时间太长,您可以这样做
function myRequest() {
return new Promise((resolve, reject) => {
var mytimeout = setTimeout(function() {
console.log('We are sorry but your request took too long');
reject({
err: "timed out"
});
}, 10)
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(res => {
resolve(res);
clearTimeout(mytimeout)
});
});
}
var promise = myRequest()
.then(res => console.log(res))
.catch(err => console.log(err))
尝试更改setTimeout
的超时值,对于较小的值,它将引发异常,而在超时时,将使用数据来解决诺言