Грешка в конструктора Promise() не се обработва от метода .catch().

Когато стартирам следното в Chrome, получавам съобщение за грешка „Uncaught (in promise) error“:

var p = new Promise(function(resolve){
	throw "failure";
})

p.then(function(){
	console.log("success");
})

p.catch(function(err){
	console.log(err);
});

Не получавам грешка, ако стартирам:

var p = new Promise(function(resolve){
	throw "failure";
})

p.then(function(){
	console.log("success");
}).catch(function(err){
	console.log(err);
});

или това:

var p = new Promise(function(resolve){
	throw "failure";
}).catch(function(err){
	console.log(err);
});

Какво става тук? Сравнително нов съм в Promises, така че вероятно пропускам нещо просто...


person Al R.    schedule 12.03.2018    source източник
comment
Това е обещанието, създадено от p.then(…), което се отхвърля без манипулатор   -  person Bergi    schedule 13.03.2018
comment
Сигурен съм, че има дубликат, но това е единственото нещо, което успях да намеря   -  person Bergi    schedule 13.03.2018


Отговори (2)


Първият случай не работи за вас, защото сте се опитали да уловите грешката от Promise директно там, където сте използвали в същото време .then, в този случай улавяте грешката от .then. От друга страна, където няма .then, можете да хванете директно от обекта Promise.
.catch е по-кратък псевдоним за .then. Методът catch() връща обект Promise и се занимава само със случаи, когато първоначалното обещание е отхвърлено. Има същия ефект като извикването на Promise.prototype.then(undefined, ifRejected) (това всъщност се случва в двигателя, obj.catch(onRejected) се превежда в obj.then(undefined, onRejected)). Така че не можете да поставите Promise.catch().

person Nadhir Houari    schedule 12.03.2018

Урок тук. Ако свържете своите .then() и .catch() манипулатори директно към обещанието (без да създавате междинна p променлива и междинни вериги на обещания) и имате .catch() манипулатор в края на всяка верига, е много малко вероятно (може би напълно малко вероятно) да получите " необработено съобщение за отхвърляне на обещание.

Въз основа на други случаи на това, които съм виждал както в собствения си код, така и тук при препълване на стека, струва ми се, че интерпретаторът или библиотеката с обещания донякъде отгатва, когато възникне необработена ситуация на отхвърляне и не е перфектен в отгатването си.

Във вашия случай интерпретаторът видя, че p.then() няма .catch() манипулатор и след това видя p да бъде отхвърлен. Така че тази обещаваща верига всъщност няма манипулатор .catch(). Така че тази верига от обещания ще завърши с отхвърляне и няма манипулатор. Това задейства предупреждението.

Не беше достатъчно умен да види, че има отделно p.catch() или не смяташе, че е оправдано да не показва предупреждението.

Както вече разбрахте, това винаги ще бъде безопасно:

new Promise(function(resolve){
    throw "failure";
}).then(function(data) {
    console.log(data);
}).catch(function(err){
    console.log(err);
});

защото няма обещаващи вериги, които някога могат да получат отказ, който не е уловен от .catch(). Помислете два пъти дали изобщо да запазите обещание към променлива - просто направете една верига обещания (или разклонени вериги вътре в .then() манипулатори, ако е необходимо). Почти никога не съм намирал за необходимо да запиша обещание в променлива, освен понякога, когато го връщам от функция и изпълнявам някакъв код във функцията, след като обещанието е създадено. Обикновено можете просто да направите:

f().then(...).then(...).catch(...);
person jfriend00    schedule 13.03.2018