Я изучаю, как использовать Promise без библиотек. Из того, что я прочитал, я мог объединить Promise вместе, а затем добавить .catch
в конце для обработки ошибок.
Что я ожидаю
Поэтому, если я изменю URL-адрес на какой-то неверный URL-адрес, не должен ли я улавливать ошибку и останавливать выполнение всей программы?
Что я вижу сейчас?
Когда я помещаю ложный url, программа просто выдает ошибку, а не обрабатывает ее как отказ.
const request = require("request");
new Promise((resolve, reject) => {
request(
"http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
(err, res, body) => {
if (err) {
reject("bad call on geo code!");
}
resolve(JSON.parse(body).results[0].geometry.location);
}
);
})
.then(res => {
const {lat, lng} = res;
return new Promise((resolve, reject) => {
request(
'https://api.darksky.net/forecast/6fb416a8313aabd902a22558e07cc032/${lat},${lng}',
(err, res, body) => {
if (err) {
reject("bad call on darksky");
}
resolve(JSON.parse(body));
}
);
});
})
.then(res => {
const currentTemp = res.currently.temperature;
const feelTemp = res.currently.apparentTemperature;
const temps = {currentTemp, feelTemp};
return new Promise((resolve, reject) => {
request(
"http://ron-swanson-quotes.herokuapp.com/v2/quotes",
(err, res, body) => {
if (err) {
reject("bad call on quotes");
}
resolve({temps, body});
}
);
});
})
.then(res => {
console.log(
'Today weather is ${res.temps.currentTemp}, and it feels like ${res
.temps
.feelTemp}! \nAnd here is your stupid quote of the day: \n${JSON.parse(
res.body
)[0]}'
);
})
.catch(err => {
console.log(err);
});
Сообщение об ошибке:
Это не имеет особого смысла, в основном ошибка не остановила программу, которая просто перешла к следующему обещанию. Это обещание получило ошибку, но не могло разобрать ее, потому что она не в ожидаемом формате JSON.
SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at Promise.then.then.then.res (/Users/leoqiu/reacto/playground/6_promiseMethod.js:48:74)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
Когда вы вызываете reject()
внутри вашего оператора if
, вы не возвращаетесь, и вы не используете else
чтобы ваше resolve(JSON.parse(body).results[0].geometry.location);
все еще выполняется, и это создает исключение.
Вы можете изменить это:
new Promise((resolve, reject) => {
request(
"http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
(err, res, body) => {
if (err) {
reject("bad call on geo code!");
return;
}
resolve(JSON.parse(body).results[0].geometry.location);
}
);
})
Это распространенная ошибка, которую люди думают, что reject()
работает как break
или какой-то другой оператор потока управления, потому что reject()
- это тип потока управления обещаниями. Но это не останавливает выполнение в вашем блоке, поэтому вам нужно либо return
после него, либо использовать else
.
Или я предпочитаю использовать if/else
потому что я думаю, что это делает логику еще более очевидной:
new Promise((resolve, reject) => {
request(
"http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
(err, res, body) => {
if (err) {
reject("bad call on geo code!");
} else {
resolve(JSON.parse(body).results[0].geometry.location);
}
}
);
})
Основываясь на предложении Патрика Эванса...
reject
не останавливает выполнение программы, поэтому сообщение об ошибке переходит к следующему обещанию, поэтому возникает ошибка json
parsing.
Решение просто return
результат отклонения.
if (err) {
reject("bad call on geo code!");
return err;
}
res
для следующего обещания. Таким образом, ошибка - просто ошибка анализа JSON.