Смутить ошибку и отказаться от обещания
Все:
Я новичок в JS Promise, есть одна путаница, когда дело доходит до цепочки Promise, скажем, у меня есть цепочка обещаний вроде:
var p = new Promise(function(res, rej){
})
.then(
function(data){
},
function(err){
})
.then(
function(data){
},
function(err){
})
.catch(
function(err){
})
Что меня смущает:
- Когда функция (err) вызывается и когда вызов catch вызывается?
- Как разрешить и отклонить в
then
?
Спасибо
Ответы
Ответ 1
Формуляр для использования обещания:
var p = new Promise(function(resolve, reject) {
var condition = doSomething();
if (condition) {
resolve(data);
} else {
reject(err);
}
});
Нет ничего особенного в .catch
, это просто сахар для .then (undefined, func)
, но .catch
более четко сообщает, что он является чисто обработчиком ошибок.
Если a Promise
не разрешает и в нем не предоставляется обратный вызов отклонения, он переходит к следующему .then
в цепочке с обратным вызовом отказа. Обратный вызов отклонения - reject(err)
.
Более подробные объяснения см. в разделе Javascript Promises - снова и снова.
То есть: в вашем примере. catch
только вызывается, если в предыдущем обратном вызове отклонения есть ошибка. То есть есть ошибка в самой функции reject(err)
, которая не имеет ничего общего с предыдущим Promise
не разрешающим.
Вы можете ограничить себя обратным вызовом отклонения в .catch
в конце цепочки .then
. Любой Error
в любом .then
затем перейдет к .catch
. Одна тонкость: любая ошибка в .catch
не попадает.
Ответ 2
Важно знать, что метод .then() всегда привязан к Promise и возвращает новое обещание, значение которого и разрешенное/отклоненное состояние основано на возвращаемой функции.
В вашем примере, если исходное обещание разрешится, тогда первая функция в вашем первом .then() будет вызвана с разрешенным значением. Если он возвращает значение, то любое значение, которое он возвращает, будет затем передано в первую функцию во второй .then(). Функция в catch никогда не будет вызвана.
Если Promise отвергает, вторая функция в вашем первом .then() будет вызвана с отклоненным значением, и любое возвращаемое значение станет новым разрешенным обещанием, которое затем переходит в первую функцию вашего второго. Поймать здесь тоже нельзя. Это только в том случае, если Promise отклоняет и вы отказываетесь от отклонения Promises или бросаете ошибки в ваших функциях function(err){}
, которые вы получите в function(err){}
в вашем блоке catch.
Чтобы разрешить ваши функции function(data){}
, все, что вам нужно сделать, это вернуть значение (или вернуть Promise/thenable, который позже будет разрешен).
Чтобы отклонить, вам нужно либо выбросить ошибку, фактически вызвать ошибку, вернуть новое обещание, которое в конечном итоге отклонит, либо явно вернуть Promise.reject(::some value::)
.
Чтобы разрешить в ваших блоках function(err){}
, все, что вам нужно сделать, это вернуть новое значение. Вы также можете вернуть Promise, и в этом случае Promise - это то, что будет возвращено (в конечном счете, разрешение или отклонение).
В общем случае нецелесообразно определять как разрешенный, так и отклоненный путь в том же .then(), хотя: PROMISE.then(fn).catch(fn)
является гораздо более безопасной/более четкой практикой, потому что тогда любые ошибки в первом .then() будут пойманный уловом. Если вы делаете PROMISE.then(fn, fn)
вместо этого, хотя, если в первой функции произошла ошибка, она не будет застигнута второй: некоторые из них позже привязаны к методу, чтобы поймать ее.
Ответ 3
-
Обратите внимание на пример функции-исполнителя в
var p = new Promise(function(res, rej){});
является неполным. Действительная функция-исполнитель, предоставленная конструктору Promise, должна вызвать свой первый аргумент (res
), чтобы разрешить построенное обещание или его второй аргумент (rej
), чтобы отклонить обещание. Эти вызовы обычно выполняются асинхронно, но не обязательно должны быть в ES6.
-
Когда обещание разрешается с помощью объекта Promise (или любого объекта с свойством .then
, который является функцией), ничего не происходит, пока объект обещания, предоставленный в самом разрешении, не станет выполненным или отвергнута. Выполненные значения передаются обработчикам .then
onFulfilled
, отклоненные значения передаются .then
onRejected
обработчикам/слушателям/обратным вызовам (в зависимости от вашей терминологии).
-
Но когда обещание разрешено с не обещающим (вроде) объектом, слушатели, представленные в качестве первого параметра .then
, вызывают с разрешением.
-
Когда обещание отклоняется с любым значением, вызываемые в качестве второго параметра .then
или первый параметр .catch
вызываются с отклоненным значением.
-
.catch
является эвфемизмом для вызова .then
с предоставленным аргументом в качестве второго параметра и опусканием первого параметра, как в
Promise.prototype.catch = function( listener) { return this.then(null, listener);};
-
Поведение .then
зарегистрированных onFulfill
и onReject
функций одинаково. Отклонить обещанное обещание выдать ошибку. Чтобы выполнить обещание в цепочке, вы получите не обещание. Чтобы сохранить цепочку обещаний, верните обещание (или обещание).
-
(Обновление) Если параметр, предоставленный в .then( onFulfill, onReject)
отсутствует или не является объектом функции, обработка эквивалентна предоставлению фиктивной функции из:
function onFulfill( data) { return data;}
function onReject( err) { throw err;}
Это обычный случай при вызове then
или catch
с одним аргументом.