ÐбÑобники пÑомÑÑÑв .then/.catch/.finally завжди аÑинÑ
ÑоннÑ.
ÐавÑÑÑ ÐºÐ¾Ð»Ð¸ пÑомÑÑ Ð±Ñде негайно виконано, код Ñ ÑÑдкаÑ
, ÑÐºÑ ÑдÑÑÑ Ð¿ÑÑÐ»Ñ .then/.catch/.finally вÑе одно виконаÑÑÑÑÑ ÑанÑÑе ÑиÑ
обÑобникÑв.
ÐÑÑ Ð´ÐµÐ¼Ð¾:
let promise = Promise.resolve();
promise.then(() => alert("пÑомÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾!"));
alert("код виконано"); // Ñей alert показÑÑÑÑÑÑ Ð¿ÐµÑÑим
ЯкÑо ви його запÑÑÑиÑе, Ñо побаÑиÑе ÑпоÑаÑÐºÑ ÐºÐ¾Ð´ виконано, а поÑÑм пÑомÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾!.
Це дивно, адже пÑомÑÑ, безÑмовно, виконÑÑÑÑÑÑ Ð· Ñамого поÑаÑкÑ.
Ð§Ð¾Ð¼Ñ .then ÑпÑаÑÑвав пÑзнÑÑе? Що вÑдбÑваÑÑÑÑÑ?
ЧеÑга мÑкÑозадаÑ
ÐÑинÑ
ÑÐ¾Ð½Ð½Ñ Ð·Ð°Ð´Ð°ÑÑ Ð¿Ð¾ÑÑебÑÑÑÑ Ð½Ð°Ð»ÐµÐ¶Ð½Ð¾Ð³Ð¾ кеÑÑваннÑ. ÐÐ»Ñ ÑÑого ÑÑандаÑÑ ECMA визнаÑÐ°Ñ Ð²Ð½ÑÑÑÑÑÐ½Ñ ÑеÑÐ³Ñ PromiseJobs, ÑÐºÑ Ñе називаÑÑÑ âÑеÑÐ³Ð¾Ñ Ð¼ÑкÑозадаÑâ (ÑеÑмÑн v8).
Як зазнаÑено в ÑпеÑиÑÑкаÑÑÑ:
- ЧеÑга ÑÑнкÑÑонÑÑ Ð·Ð° пÑинÑипом пеÑÑим-пÑийÑов-пеÑÑим-пÑÑов: задаÑÑ, ÑÐºÑ ÑÑали в ÑеÑÐ³Ñ ÑанÑÑе â виконÑÑÑÑÑÑ ÑанÑÑе.
- ÐÐ¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð´Ð°Ñ Ð¿Ð¾ÑинаÑÑÑÑÑ Ð»Ð¸Ñе ÑодÑ, коли бÑлÑÑе нÑÑого не виконÑÑÑÑÑÑ.
Ðбо, пÑоÑÑÑÑе кажÑÑи, коли пÑомÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾, його обÑобники .then/catch/finally помÑÑаÑÑÑÑÑ Ð² ÑеÑгÑ; вони Ñе не виконанÑ. Ðоли ÑÑÑÑй JavaScript звÑлÑнÑÑÑÑÑÑ Ð²Ñд Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð¿Ð¾ÑоÑного кодÑ, вÑн беÑе задаÑÑ Ð· ÑеÑги Ñа виконÑÑ ÑÑ.
ÐÑÑ ÑÐ¾Ð¼Ñ âкод виконаноâ Ñ Ð¿ÑÐ¸ÐºÐ»Ð°Ð´Ñ Ð²Ð¸Ñе показÑÑÑÑÑÑ Ð¿ÐµÑÑим.
ÐбÑобники пÑомÑÑÑв завжди пÑÐ¾Ñ Ð¾Ð´ÑÑÑ ÑеÑез ÑÑ Ð²Ð½ÑÑÑÑÑÐ½Ñ ÑеÑгÑ.
ЯкÑо Ñ Ð»Ð°Ð½ÑÑжок з кÑлÑкоÑ
.then/catch/finally, Ñо кожен з ниÑ
виконÑÑÑÑÑÑ Ð°ÑинÑ
Ñонно. ТобÑо кожен обÑобник поÑÑаплÑÑ Ð² ÑеÑгÑ, але виконÑÑÑÑÑÑ Ð»Ð¸Ñе пÑÑÐ»Ñ Ð·Ð°Ð²ÐµÑÑÐµÐ½Ð½Ñ Ð¿Ð¾ÑоÑного ÐºÐ¾Ð´Ñ Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÑнÑиÑ
обÑобникÑв, ÑÐºÑ Ð¿Ð¾ÑÑапили в ÑеÑÐ³Ñ ÑанÑÑе.
Що ÑобиÑи, ÑкÑо поÑÑдок Ð¼Ð°Ñ Ð·Ð½Ð°ÑÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð½Ð°Ñ? Як ми можемо зÑобиÑи Ñак, Ñоб код виконано вÑдобÑажалоÑÑ Ð¿ÑÑÐ»Ñ Ð¿ÑомÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾?
Ðегко, пÑоÑÑо поÑÑавÑе його в ÑеÑÐ³Ñ Ð·Ð° Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ .then:
Promise.resolve()
.then(() => alert("пÑомÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾!"))
.then(() => alert("код виконано"));
Ð¢ÐµÐ¿ÐµÑ Ð¿Ð¾ÑÑдок вÑдповÑÐ´Ð°Ñ Ð·Ð°Ð´ÑмÑ.
ÐеобÑÐ¾Ð±Ð»ÐµÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ¸
ÐамâÑÑаÑÑе подÑÑ unhandledrejection Ð·Ñ ÑÑаÑÑÑ ÐÑомÑÑи: обÑобка помилок?
Ð¢ÐµÐ¿ÐµÑ Ð¼Ð¸ баÑимо, Ñк Ñаме JavaScript дÑзнаÑÑÑÑÑ Ð¿Ñо необÑÐ¾Ð±Ð»ÐµÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ¸.
âÐеобÑоблена помилкаâ Ð²Ð¸Ð½Ð¸ÐºÐ°Ñ ÑодÑ, коли помилка пÑомÑÑа не обÑоблÑÑÑÑÑÑ Ð² кÑнÑÑ ÑеÑги мÑкÑозадаÑ.
ÐазвиÑай, ÑкÑо ми оÑÑкÑÑмо помилкÑ, Ñо додаÑмо .catch до ланÑÑжка пÑомÑÑÑв Ð´Ð»Ñ ÑÑ Ð¾Ð±Ñобки:
let promise = Promise.reject(new Error("Ðомилка в пÑомÑÑÑ!"));
promise.catch(err => alert('ÑпÑймана'));
// не запÑÑÑиÑÑÑÑ: помилка обÑоблена
window.addEventListener('unhandledrejection', event => alert(event.reason));
Ðле ÑкÑо ми забÑдемо додаÑи .catch, ÑодÑ, коли ÑеÑга мÑкÑÐ¾Ð·Ð°Ð´Ð°Ñ Ð±Ñде поÑожнÑ, ÑÑÑÑй ÑнÑÑÑÑÑ Ð¿Ð¾Ð´ÑÑ:
let promise = Promise.reject(new Error("Ðомилка в пÑомÑÑÑ!"));
// Ðомилка в пÑомÑÑÑ!
window.addEventListener('unhandledrejection', event => alert(event.reason));
Ð Ñо, ÑкÑо ми обÑобимо Ð¿Ð¾Ð¼Ð¸Ð»ÐºÑ Ð¿ÑзнÑÑе? ÐапÑиклад оÑÑ Ñак:
let promise = Promise.reject(new Error("Ðомилка в пÑомÑÑÑ!"));
setTimeout(() => promise.catch(err => alert('ÑпÑймана')), 1000);
// Error: Ðомилка в пÑомÑÑÑ!
window.addEventListener('unhandledrejection', event => alert(event.reason));
ТепеÑ, ÑкÑо ми його запÑÑÑимо, Ñо ÑпоÑаÑÐºÑ Ð¿Ð¾Ð±Ð°Ñимо Ðомилка в пÑомÑÑÑ!, а поÑÑм ÑпÑймана.
Якби ми не знали пÑо ÑеÑÐ³Ñ Ð¼ÑкÑозадаÑ, Ñо могли б задаÑиÑÑ Ð¿Ð¸ÑаннÑм: âÐ§Ð¾Ð¼Ñ Ð·Ð°Ð¿ÑÑÑивÑÑ Ð¾Ð±Ñобник unhandledrejection? Ðи ÑпÑймали Ñа обÑобили помилкÑ!â
Ðле ÑÐµÐ¿ÐµÑ Ð¼Ð¸ ÑозÑмÑÑмо, Ñо unhandledrejection генеÑÑÑÑÑÑÑ, коли ÑеÑга мÑкÑÐ¾Ð·Ð°Ð´Ð°Ñ Ð·Ð°Ð²ÐµÑÑÑÑÑÑÑÑ: ÑÑÑÑй пеÑевÑÑÑÑ Ð¿ÑомÑÑи, Ñ, ÑкÑо бÑдÑ-Ñкий з ниÑ
знаÑ
одиÑÑÑÑ Ð² ÑÑÐ°Ð½Ñ ârejectedâ, Ñо ÑнÑÑÑÑÑÑÑÑÑ ÑÑ Ð¿Ð¾Ð´ÑÑ.
У виÑÐµÐ½Ð°Ð²ÐµÐ´ÐµÐ½Ð¾Ð¼Ñ Ð¿ÑÐ¸ÐºÐ»Ð°Ð´Ñ .catch, доданий в setTimeout, Ñакож ÑпÑаÑÑÑ. Ðле Ñе вÑдбÑваÑÑÑÑÑ Ð¿ÑзнÑÑе, пÑÑÐ»Ñ Ñого, Ñк unhandledrejection вже виникло, ÑÐ¾Ð¼Ñ Ñе Ð½Ñ Ð½Ð° Ñо не впливаÑ.
ÐÑдÑÑмки
ÐбÑобка пÑомÑÑÑв завжди аÑÐ¸Ð½Ñ Ñонна, оÑкÑлÑки вÑÑ Ð´ÑÑ Ð¿ÑомÑÑÑв пÑÐ¾Ñ Ð¾Ð´ÑÑÑ ÑеÑез внÑÑÑÑÑÐ½Ñ ÑеÑÐ³Ñ âpromise jobsâ, ÑÐºÑ Ñакож називаÑÑÑ âÑеÑÐ³Ð¾Ñ Ð¼ÑкÑозадаÑâ (ÑеÑмÑн v8).
Ð¢Ð¾Ð¼Ñ Ð¾Ð±Ñобники .then/catch/finally завжди викликаÑÑÑÑÑ Ð¿ÑÑÐ»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð¿Ð¾ÑоÑного кодÑ.
ЯкÑо нам поÑÑÑбно гаÑанÑÑваÑи, Ñо ÑÑÐ°Ð³Ð¼ÐµÐ½Ñ ÐºÐ¾Ð´Ñ Ð²Ð¸ÐºÐ¾Ð½ÑÑÑÑÑÑ Ð¿ÑÑÐ»Ñ .then/catch/finally, ми можемо додаÑи його до ланÑÑжкового Ð²Ð¸ÐºÐ»Ð¸ÐºÑ .then.
У бÑлÑÑоÑÑÑ ÑÑÑÑÑв Javascript, вклÑÑаÑÑи бÑаÑзеÑи Ñа Node.js, конÑепÑÑÑ Ð¼ÑкÑÐ¾Ð·Ð°Ð´Ð°Ñ ÑÑÑно повâÑзана з âÑиклом подÑйâ (âevent loopâ) Ñ âмакÑозадаÑамиâ. ÐÑкÑлÑки вони не маÑÑÑ Ð¿ÑÑмого вÑдноÑÐµÐ½Ð½Ñ Ð´Ð¾ пÑомÑÑÑв, вони ÑозглÑнÑÑÑ Ð² ÑнÑÑй ÑаÑÑÐ¸Ð½Ñ Ð¿ÑдÑÑÑника, Ñ ÑÑаÑÑÑ Ð¦Ð¸ÐºÐ» подÑй (event loop): мÑкÑÐ¾Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ (microtasks) Ñа макÑÐ¾Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ (macrotasks).
ÐоменÑаÑÑ
<code>, Ð´Ð»Ñ ÐºÑлÑÐºÐ¾Ñ ÑÑдкÑв â обгоÑнÑÑÑ ÑÑ Ñегом<pre>, Ð´Ð»Ñ Ð¿Ð¾Ð½Ð°Ð´ 10 ÑÑдкÑв â викоÑиÑÑовÑйÑе пÑÑоÑниÑÑ (plnkr, jsbin, codepenâ¦)