承诺中的清除超时使用最佳实践



我有一个关于clearTimeout方法的问题(对不起,提前对不起菜鸟问题(。我想知道在以下代码中清除超时的最佳位置在哪里?我有一个"getResponse(("函数,它将被多次调用。我不确定在哪里放置 clearTimeout 的最佳位置,以便在响应超时解决或拒绝后立即清除超时。谢谢

function getResponse() {
const responseTimeout = new Promise((resolve, reject) => {
let id = setTimeout(() => {
if (!messageHandled) {                       
reject(`Timed out to get response`);               
}                      
}, 3000);
});
const responsePromise = new Promise((resolve, reject) => {
// some code which returns response promise
});
return Promise.race([
responsePromise,
responseTimeout
]);
}

通常,我会在承诺本身中执行此操作,并避免两个单独承诺的开销。

function getResponse(...params) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error("Timed out to get response"))
// some code to abort request
}, 3000)
// some code which resolves promise
})
}

有用的是,承诺会在您第一次解决后忽略以后的解决方案和/或拒绝。如果可以在不触发解析逻辑的情况下以编程方式中止它,则这变得容易得多,但即使不能,也始终可以打一个布尔值来阻止未来的请求。它还可以更轻松地添加对以后取消的支持,这也很有帮助。如果你还需要关闭超时(如果你正在做一些 DOM 突变或文件读取 - 你很少需要这样做(,你可以做这样的事情:

function getResponse(...params) {
return new Promise((reallyResolve, reallyReject) => {
let resolved = false
let id = setTimeout(() => {
reject(new Error("Timed out to get response"))
abort()
}, 3000)
// I'll use these instead of the `resolve`/`reject` callbacks directly.
function resolve(value) {
if (resolved) return
resolved = true
clearTimeout(id)
reallyResolve(value)
}
function reject(value) {
if (resolved) return
resolved = true
clearTimeout(id)
reallyReject(value)
}
function abort() {
// some code to abort request
}
// some code which resolves promise
})
}

这使得我不必担心编排所有内容,但它仍然有效。

如果您不需要中止逻辑(您只需要它用于网络请求和类似(,这就会变得简单得多:

function timeout(ms) {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error("Timed out")), ms)
})
}
function getResponse(...params) {
return Promise.race([
timeout(3000),
doSomethingAsync(),
])
}

最新更新