以下是我要在nodejs中执行的操作。 Rest API将城市名称作为输入。我正在尝试使用输入城市的地理编码API来获取经度和纬度。 然后,我正在尝试使用纬度和经度,使用其他API获取最近城市的列表。 然后,对于所有这些城市,我正在获取天气报告,对于这些城市,然后,我正在获取是否有水,并将其作为JSON返回。
如您所见,有很多 then ,此练习的目的是避免嵌套回调。
我正在使用async / await,它应该消除了嵌套的then函数。但是我看不到另一种方法。完整的代码段如下。我要修复的丑陋部分是requester.makeRequest()
以下仅是必要代码的片段,而不是完整的工作代码。任何有关如何解开此问题的帮助将不胜感激。
app.get('/search', function(req, res, next) {
const requester = {
lastRequest: new Date(),
makeRequest: async function(url) {
const response = await fetch(url);
const json = await response.json();
return json;
}
};
requester.makeRequest(geocode_url +`?locate=${req.query.q}&json=1`
+ geocode_token)
.then(function(city){
var final_result = []
var lat = city.latt;
var long = city.longt;
// request to get list of cities closer to that location,
//takes latitude and longitude as parameters
requester.makeRequest(metaweather_url + '?lattlong='
+ lat + ',' + long)
.then(function(closer_cities) {
var cities_len = closer_cities.length
for(i = 0; i < closer_cities.length; i++) {
woeid = closer_cities[i].woeid
//request to get weather using woeid parameter
requester.makeRequest(woeid_url + woeid)
.then(function(weather) {
var lattlong = weather.latt_long;
requester.makeRequest(onwater_url+ lattlong +
'?access_token=' + water_access_token)
.then(function(onwater) {
var temp = Object.assign(weather, onwater)
final_result.push(temp)
if (final_result.length == cities_len) {
res.status(200).json({error: false,
data: {message: final_result}})
}
})
})
}
})
})
})
答案 0 :(得分:2)
我想你那时还需要一个
requester.makeRequest(geocode_url +`?locate=${req.query.q}&json=1`
+ geocode_token)
.then(async function(city){
var final_result = []
var lat = city.latt;
var long = city.longt;
// request to get list of cities closer to that location,
//takes latitude and longitude as parameters
closer_cities = await requester.makeRequest(metaweather_url + '?lattlong='+ lat + ',' + long);
var cities_len = closer_cities.length;
for(i = 0; i < closer_cities.length; i++) {
woeid = closer_cities[i].woeid
//request to get weather using woeid parameter
weather = await requester.makeRequest(woeid_url + woeid)
var lattlong = weather.latt_long;
onwater = await awaitrequester.makeRequest(onwater_url+ lattlong + '?access_token=' + water_access_token)
var temp = Object.assign(weather, onwater)
final_result.push(temp)
if (final_result.length == cities_len) {
res.status(200).json({error: false, data: {message: final_result}})
}
}
})
编辑:我真的不认为我的回答与您的问题有关
答案 1 :(得分:2)
此行:requester.makeRequest ... .then(function(city){
将.then(function(city){
替换为var city = await requester.makeRequest
,city
将具有应许的兑现价值,其余then
s则应这样做:
(请注意,await
仅在async
函数内部使用,可以使用iife)
(async () => {
var city = await requester.makeRequest(`${geocode_url}?locate=${req.query.q}&json=1${geocode_token}`);
var final_result = []
var lat = city.latt;
var long = city.longt;
// request to get list of cities closer to that location,
//takes latitude and longitude as parameters
var closer_cities = await requester.makeRequest(`${metaweather_url}?lattlong=${lat},${long}`);
var cities_len = closer_cities.length;
for (i = 0; i < closer_cities.length; i++) {
woeid = closer_cities[i].woeid
//request to get weather using woeid parameter
var weather = await requester.makeRequest(woeid_url + woeid);
var lattlong = weather.latt_long;
var onwater = await requester.makeRequest(`${onwater_url}${lattlong}?access_token=${water_access_token}`);
var temp = Object.assign(weather, onwater)
final_result.push(temp)
if (final_result.length == cities_len) {
res.status(200).json({
error: false,
data: {
message: final_result
}
})
}
}
})();
答案 2 :(得分:1)
then
首先被滥用,因为它会导致回调地狱。 Promise是基于回调的,但它们支持链接,该链接应消除嵌套的回调。
应该是:
requester.makeRequest(geocode_url +`?locate=${req.query.q}&json=1` + geocode_token)
.then(function(city){
var final_result = []
var lat = city.latt;
var long = city.longt;
return requester.makeRequest(metaweather_url + '?lattlong='
+ lat + ',' + long)
})
.then(function(closer_cities) {
...
});
如果then
中有一个承诺,则应将其返回。这样一来,回调嵌套就不会超过一个级别。
await
是then
的语法糖,拒绝也应处理:
app.get('/search', function(req, res, next) {
try {
...
const city = await requester.makeRequest(geocode_url +`?locate=${req.query.q}&json=1`
+ geocode_token);
var final_result = []
var lat = city.latt;
var long = city.longt;
const closer_cities = await requester.makeRequest(metaweather_url + '?lattlong='
+ lat + ',' + long);
...
} catch (err) {
next(err)
}
});
答案 3 :(得分:1)
在调用async
函数时,您不应该使用.then(...)
构造...
只需let result = await myAsynchronousFunction(a, b, c);
...