我有一个返回 Promise 的函数。当我在
.then()
或 .catch()
块中使用完 Promise 后,我总是想执行相同的清理代码。我当前的设置是这样的:
const promiseWithFinally = () => {
return new Promise((resolve, reject) => {
// resolve or reject at some point
}).finally(() => console.log('finally done'))
}
promiseWithFinally()
.then(() => console.log('then done'))
.catch(() => console.log('catch done'))
我想要发生的是首先记录
then done
或catch done
,然后记录finally done
。然而,它似乎以完全相反的顺序执行 - 当我在 5 秒超时后解析 Promise 时,finally done
在 5 秒后首先被记录,然后立即 then done
。
我做错了什么或者一般可以这样做吗?我知道我可以将
.finally()
附加到每个单独的函数调用中,但由于它始终相同,我想将其放在函数定义中。
不,这是不可能的。最后用于在给定的承诺之后进行清理,而不是其
then
或 catch
方法。
您可以做的是将
then
和 catch
方法传递给将附加在 finally
之前的函数:
const promiseWithFinally = (chain) => {
return new Promise((resolve, reject) => {
// resolve or reject at some point
setTimeout(resolve, 1000);
}).then(chain.then, chain.catch).finally(() => console.log('finally done'))
}
promiseWithFinally({
then: () => console.log('then done'),
catch: () => console.log('catch done')
})
不,这是不可能的,因为你不能依赖于finally 何时运行。
const cleanupFunc = () => {
console.log('Cleaning up.');
};
const someAsyncMethod = (thenFunc, catchFunc) => {
new Promise(
(resolve, reject) => {
setTimeout(() => resolve(), 5000);
},
)
.then((...args) => {
try {
thenFunc(...args);
} catch (err) {
}
cleanupFunc();
})
.catch((...args) => {
try {
catchFunc(...args);
} catch (err) {
}
cleanupFunc();
});
};
someAsyncMethod((result) => console.log('Then done'), (err) => console.log('Catch done'));
虽然不可能依赖于finally,但你可以做的是编写一个需要执行一些异步操作并返回promise的函数。在我的示例中,此操作等待 5 秒超时,但他也可以是返回 Promise 的异步 api 调用。
下一步是向异步操作返回的 Promise 添加 then 和 catch 调用,这两个调用都以 try 子句开头,在其中调用属于解析类型的回调参数(thenFunc 为 then,catchFunc 为 catch ) 后跟一个 catch,它不执行任何操作并以调用清理函数结束。通过这种方式,您可以确定无论在运行 then 或 catch 回调期间发生什么,都会调用清理函数。
假设您知道该 Promise 的其余处理程序将同步附加,并且处理程序中的所有操作都是同步的,这是可能的,尽管有点 hacky。
只需让finally 处理程序在最后重新附加自身即可:
const promiseWithFinally = () => {
const thisPromise = new Promise((resolve, reject) => {
// Rejection example
setTimeout(reject, 200);
}).finally(() => {
setTimeout(() => {
thisPromise.finally(() => console.log('finally done')).catch(() => {});
}, 0);
});
return thisPromise;
};
promiseWithFinally()
.then(() => console.log('then done'))
.catch(() => console.log('catch done'));
有一个涉及承诺的解决方案。 需要注意的是,如果返回的 Promise 对象的用户执行类似的“hack”,它将不起作用。
const promise = new Promise((resolve, reject) => resolve());
promise.finally(() => promise.finally(() => console.log("cleanup")));
promise.then(() => console.log("do me first!"));
这个概念是,在 Promise 链中执行的第一个回调可以将任何它想要的内容附加到 Promise 链的末尾。当然,如果下一个回调做了同样的事情,你就不走运了,这是这种方法的局限性。