Ответ 1
В общем, вы можете думать о том, что отвергаете как аналог синхронного throw
и выполняете аналогию с синхронным return
. Вы должны отклонять всякий раз, когда функция каким-то образом не увенчалась успехом. Это может быть тайм-аут, сетевая ошибка, неправильный ввод и т.д. И т.д.
Отклонение обещания, как и исключение, полезно для потока управления. Он не должен представлять собой поистине непредвиденную ошибку; он может представлять проблему, которую вы полностью ожидаете и обрабатываете:
function getProfile(email) {
return getProfileOverNetwork(email)
.then(null, function (err) {
//something went wrong getting the profile
if (err.code === 'NonExistantUser') {
return defaultUser;
} else if (profileCached(email)) {
return getProfileFromCache(email);//fall back to cached profile
} else {
throw err;//sometimes we don't have a nice way of handling it
}
})
}
Отказ позволяет нам перепрыгнуть через нормальное поведение успеха, пока мы не перейдем к методу, который знает, как его обрабатывать. В качестве другого примера у нас может быть некоторая функция, которая глубоко вложена в нижней части стека приложений, которая отвергает. Это может не обрабатываться до самого верха стека, где мы могли бы его зарегистрировать. Дело в том, что отклонения перемещаются по стеку точно так же, как исключения выполняются в синхронном коде.
В общем, везде, где это возможно, если вы пытаетесь написать какой-то асинхронный код, вы должны подумать: "Что бы я написал, если бы это было синхронно". Обычно это довольно простая трансформация, чтобы получить от этого обещанный эквивалент.
A nice example of where rejected promises might be used is in an
существует`:
function exists(filePath) {
return stat(filePath) //where stat gets last updated time etc. of the file
.then(function () { return true; }, function () { return false; })
}
Обратите внимание, что в этом случае отклонение полностью ожидается и просто означает, что файл не существует. Обратите также внимание на то, как он параллелен синхронной функции:
function existsSync(filePath) {
try {
statSync(filePath);
return true;
} catch (ex) {
return false;
}
}
Ваш пример
Возвращаясь к вашему примеру:
Я бы предпочел отклонить обещание, полученное в результате findUserByEmail
, если ни один пользователь не был найден. Это то, что вы в полной мере ожидаете иногда случиться, но это исключение из нормы и, вероятно, должно быть обработано аналогично всем другим ошибкам. Аналогично, если бы я писал синхронную функцию, у меня было бы это throw
исключение.
Иногда может быть полезно просто вернуть null
вместо этого, но это будет зависеть от вашей логики приложений и, вероятно, не лучший способ пойти.