你能用预定义的finally返回Promise吗



我有一个返回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 donecatch done,然后再记录finally done。然而,它似乎以完全相反的顺序执行——当我在超时5秒后解析Promise时,finally done在5秒后首先被记录,然后立即被记录then done

我做错了什么,或者总的来说有可能这样做吗?我知道我可以把.finally()附加到每个单独的函数调用中,但由于它总是一样的,我想把它放在函数定义中。

不,这是不可能的。最后是在给定的承诺之后进行清理,而不是针对其thencatch方法。

您可以将thencatch方法传递给将附加在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')
})

简短回答

不,这是不可能的,因为你不能依赖最终被运行的时间。

更长的答案和可能的解决方案

代码

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'));

解释

Al尽管最终不可能依赖,但您可以编写一个函数,该函数需要执行一些异步操作来返回promise。在我的示例中,此操作等待5秒的超时,但例如,他的操作也可以是返回promise的异步api调用。

下一步是向异步操作返回的promise添加一个then和一个catch调用,这两个调用都以try子句开始,在try子句中,您调用属于解析类型的回调参数(thenFunc表示then,catchFunc表示catch(,然后是一个不执行任何操作的catch,以调用cleanup函数结束。通过这种方式,您可以确信无论在运行then或catch回调过程中发生什么,都会调用cleanup函数。

假设您知道该promise的其余处理程序将同步附加,并且处理程序中的所有操作都是同步的,这是可能的,尽管有点麻烦。

只需让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'));

最新更新