Я хочу запустить одно и то же действие, независимо от того, успешно разрешено ли мое обещание или нет. Я не хочу связывать одну и ту же функцию с обоими аргументами .then
. Разве нет .always
, как у jQuery? Если нет, как мне это достичь?ES6 обещание установленный обратный вызов?
ответ
Нет ли
.always
, как у jQuery?
No, there's not (yet). Хотя есть active proposal, возможно, ES2018.
Если нет, то как мне это достичь?
Вы можете реализовать finally
метод самостоятельно, как это:
Promise.prototype.finally = function(cb) {
const res =() => this
const fin =() => Promise.resolve(cb()).then(res)
return this.then(fin, fin);
};
или более широко, с прохождением информации разрешения на обратный вызов:
Promise.prototype.finally = function(cb) {
const res =() => this
return this.then(value =>
Promise.resolve(cb({state:"fulfilled", value})).then(res)
, reason =>
Promise.resolve(cb({state:"rejected", reason})).then(res)
);
};
И гарантировать, что оригинальное разрешение поддерживается (когда в обратном вызове нет исключения), и что обещания ожидаются.
С асинхронной/Await, вы можете сочетание await
с try/finally
, например, так:
async function(somePromise) {
try {
await somePromise();
} finally {
// always run this-- even if `somePromise` threw something
}
}
Вот реальный пример, который я запущен в производство с узлом, используя async-to-generator плагин Бабеля.
// Wrap promisified function in a transaction block
export function transaction(func) {
return db.sequelize.transaction().then(async t => {
Sequelize.cls.set('transaction', t);
try {
await func();
} finally {
await t.rollback();
}
});
}
Я использую этот код в тесте мокко наряду с Sequelize ORM начать транзакцию БД, и независимо от результата БД вызывает в тесте, всегда откатить в конце.
Это примерно аналогично методу Bluebird .finally()
, но IMO, гораздо более приятный синтаксис!
(Примечание:.. В случае, если вам интересно, почему я не await
ИНГ на первом Promise- это деталь реализации Sequelize Он использует CLS для «привязки» транзакции SQL к Promise цепи Все это приводит к тому, что внутри та же цепочка привязана к транзакции. Ничего снаружи нет. Поэтому ожидание обещания «закрыло» блок транзакций и сломал цепочку. Я бросил этот пример, чтобы показать вам, как «ваниль» «Совместимость с обещаниями может быть смешана вместе с асинхронными функциями и хорошо работать вместе.)
Почему вы не используете транзакцию async-функции и не вызываете вызов 'then'? – Bergi
Уход! Никогда не думал об использовании 'try/finally' с' async/await'. Это пригодится. – mpen
@Bergi - Sequelize использует что-то, называемое CLS, чтобы охватить блок транзакций цепочкой Promise. Если я использовал 'await', он вернул обработчик транзакции, но последующий SQL был бы _outside_ блока и, следовательно, не привязан к транзакции. Это деталь реализации Sequelize. –
Если вы не обновите прототип, не можете обновить его:
executeMyPromise()
.then(function(res){ return {res: res}; })
.catch(function(err){ return {err: err}; })
.then(function(data) {
// do finally stuff
if (data.err) {
throw data.err;
}
return data.res;
}).catch(function(err) {
// handle error
});
Я не думаю, что это то же самое. См. Здесь [3-й и 4-й пункты] (https://github.com/tc39/proposal-promise-finally#why-not-thenf-f). Мы можем фактически использовать решение Берги без изменения прототипа. Вам просто нужно называть это смешным: 'finallyFunc.call (thePromise, callback)'. Хорошо работает с оператором bind. – mpen
@mpen, ты прав. Отредактировано с исправлением. – user2426679
Вот моя реализация .finally().
Promise.prototype.finally = function(cb) {
return this.then(v=>Promise.resolve(cb(v)),
v=>Promise.reject(cb(v)));
};
Я тестировал:
(new Promise((resolve,reject)=>{resolve(5);})).finally(x=>console.log(x)); //5
(new Promise((resolve,reject)=>{reject(6);})).finally(x=>console.log(x)); //6
(new Promise((resolve,reject)=>{reject(7);}))
.then(x=>x,y=>y)
.catch(x=>{throw "error";})
.finally(x=>{console.log(x); throw "error"; return x;}) // 7
.then(x=>console.log(x),y=>console.log('e')); //e
// Uncaught (in promise) undefined
Нет необходимости вводить новые понятия
const promise = new Promise((resolve, reject) => {
/*some code here*/
});
promise.then(() => {
/* execute success code */
},() => {
/* execute failure code here */
}).then(() => {},() => {}).then(() => {
/* finally code here */
});
Это приведет к возврату возвращаемого значения из первой ветки .then(), не так ли? – thenickdude
Это правильно. –
Продлить Bergi ответ.
Возврат Promise.reject() в обработчике улова предотвратит финализацию «then» для вызова.
Так что, если вы собираетесь обрабатывать ошибки обещания 2+ раз вы должны использовать шаблонный так:
return myPromise()
.then(() => ...)
.catch((error) => {
...
myFinnaly();
return Promise.reject(error);
})
.then(() => myFinnaly());
- 1. Обещание не вызывать «затем» обратный вызов
- 2. Обратный вызов/обещание не работает правильно
- 3. машинописный синтаксис angular2 обещание затем обратный вызов
- 4. как преобразовать обратный вызов в обещание
- 5. ES6 обещание выполнить заказ
- 6. Простой выход из генератора ES6, когда библиотека использует обратный вызов
- 7. Могут ли генераторы ES6 передавать данные, обычно передаваемые на обратный вызов/обещание?
- 8. Обратный звонок или обещание?
- 9. Как повторить обещание в ES6
- 10. Можно ли клонировать обещание ES6?
- 11. Как понять дерево es6 обещание
- 12. Установка es6-обещание с типом
- 13. Угловой обратный вызов, не возвращающий данные в Угловое обещание
- 14. Выход обещание цепь на первый обратный вызов ошибки
- 15. Как преобразовать обещание в обратный вызов в узле js?
- 16. Угловой обратный вызов или обещание ловушки возврата vale
- 17. Лучше ли использовать обратный вызов или обещание в Угловом 2?
- 18. Создайте api, который принимает обратный вызов, а также возвращает обещание
- 19. Могу ли я преобразовать обратный вызов в обещание?
- 20. Обратный вызов AngularJS, скопируйте поведение $ http. Превратите кеш в обещание
- 21. JS: Refactor функция мульти-обратный вызов в обещание
- 22. Мое угловое обещание неожиданно идет на обратный вызов ошибки, почему?
- 23. Возвращая ценность от обещания: обратный вызов или обещание?
- 24. Как преобразовать этот отложенное обещание стиля, чтобы обещание ES6
- 25. Обещание в машинописных текстах - es6-обещание типа не доступно
- 26. AngularFire 2 - Обратный вызов Auth.logout()
- 27. Bootbox 'загруженный' обратный вызов
- 28. Определить обещание как метод класса ES6
- 29. ES6 Согласие на обещание и класс
- 30. Устранить обещание ES6 с первым успехом?
вы не можете сделать .finally (функция() {...})? –
См. Http://stackoverflow.com/questions/26667598/will-javascript-es6-promise-support-done-api –
@CharlieWynn Это не определено в Babel и не указано в [MDN] (https: //developer.mozilla. орг/EN-US/Docs/Web/JavaScript/Справка/Global_Objects/Promise/улова). – mpen