Ошибка в конструкторе Promise() не обрабатывается методом .catch()

Когда я запускаю в Chrome следующее, я получаю сообщение об ошибке «Uncaught (in promise) failure»:

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)


Первый случай не сработал для вас, потому что вы пытались перехватить ошибку из промиса непосредственно там, где вы использовали в то же время .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