Я пишу библиотеку в nodejs, которая обертывает другую библиотеку. мой код выглядит примерно так:
function wrapper(functionToWrap) {
return function(param1, param2) {
try {
return functionToWrap(param1, param2);
} catch(err) {
console.log(err);
throw err;
} finally {
finalizeWrapping();
}
}
}
проблема в том, что моя функция finalizeWrapping
- это функция, которая ждет обещаний, которые я собираю (путем размещения некоторых перехватов перед вызовом функцииToWrap для некоторых асинхронных apis, которые она использует) для разрешения и только затем действует примерно так:
function finalizeWrapping() {
Promise.all(pendingPromises).then(function(values) {
//finalize the wrapping
console.log('all promises fulfilled!');
});
}
проблема заключается в том, что ошибка вызывается, и узел выходит (эта ошибка не должна обрабатываться, поскольку обернутая функция не обрабатывает ее) до того, как все обещания будут разрешены, а затем будет выполнен блок.
мой вопрос: есть ли что-нибудь, что я могу сделать для того, чтобы обойти это, что означает, что он должен правильно выполнить ошибку пользователю и закончить выполнение тогдашнего блока, или мне нужно изменить способ привязки apis к синхронному и не использовать обещание?
Спасибо заранее всем помощникам :)
EDIT: попытка сделать мой вопрос яснее - functionToWrap
- это не моя функция, это функция другой библиотеки (и она может измениться - это означает, что мой код сможет обернуть как можно больше функций). этой функции разрешено использовать async apis (который я могу попробовать для monkeypatch), и в основном он должен иметь как можно меньше ограничений - я хочу, чтобы пользователь мог написать любую функцию, и я мог ее обернуть.
Не уверен, что следующее может помочь, у вас может не хватить репутации для комментариев, хотя я думаю, что вы можете прокомментировать свой собственный вопрос, и он отвечает.
const wrapper = functionToWrap =>
function() {
//special type to indicate failed call to functionToWrap
const Fail = function(reason){this.reason=reason;};
//does not matter how many argument. Assuming functionToWrap
// does not rely on "this". If it does then also pass the
// object that functionToWrap is on and replace null with that object
return Promise.resolve(Array.from(arguments))
.then(
//if functionToWrap is on an object pass it to wrapper
// and replace null with that object
args=>functionToWrap.apply(null,args)
)
.catch(
//if functionToWrap throws an error or rejects we will catch it here
// and resolve with a special Fail type value
err=>{
console.log(err);
return new Fail(err)
}
).then(
//since promise cannot fail (its rejection is caught and resolves with Fail)
// this will always be called
//finalize should return Promise.all... and maybe not use a shared
// variable called pendingPromises, global shared mutable variables in async
// functions is asking for trouble
result=>finalizeWrapping().then(
()=>
//if functionToWrap rejected or thew the result will be a Fail type
(result && result.constructor === Fail)
? Promise.reject(result.reason)//reject with the original error
: result//resolve with the functionToWrap result
)
);
}
finalizeWrapping
и если функция, вызывающая обернутую функцию, должна знать, finalizeWrapping
ли finalizeWrapping
и когда она завершена, вы должны вернуть обещание, потому что finalizeWrapping
является асинхронным.
wrapper
возвращала обещание (которое разрешается вfinally
), или измените методfinaliseWrapping
на синхронный (но я предполагаю, что это невозможно, иначе вы, вероятно, имели бы сделал это! :)