基本上,我想知道如何在网页更新之前完成代码的加载。我听说了promise或async的工作,但是我无法在我的代码中正确使用它们。我在下面做了一个简单的代码版本。目前,当我加载页面时,我的天气功能已正确更新,但是flickr API需要再加载两次页面才能显示其结果。有人可以告诉我如何使用异步或Promises加载我的所有数据并立即更新页面吗?
app.get('/', function (req, res) {
// Render the webpage
res.render('index', {weather: null, headlocation: null, lat: null, long: null, imgLinks: null, WebLinks: null, imgLinksFl: null, restLat: null, restLong: null, restname: null, error: null});
})
// Main Page
app.post('/', function (req, res) {
city = req.body.city; // Grab the users input city
//console.log(weatherSort); // Debugging
weatherSearch(); // Openweather API
filckrSearch(); // Flickr API
res.render('index', {weather: weatherText, headlocation: headLocationText, lat: latLocation, long: longLocation, imgLinks: imageLinks, WebLinks: websiteLinks, imgLinksFl: imageLinksFlick, restLat: latitudeRest, restLong: longitudeRest, restname: restName, error: null});
});
// Weather function
function weatherSearch(){
// API URL
let urlw = `http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${apiKeyWeather}`
// Send out a request
request(urlw, function (err, response, bodyW) {
// Check for errors
if(err || (JSON.parse(bodyW).cod == '404') || (JSON.parse(bodyW).cod == '401')){
// If errors are found initialize all variables to empty so that it protects from future errors
// in other API functions
} else {
let weather = JSON.parse(bodyW) // Get JSON result
weatherText = `It's ${weather.main.temp} degrees in ${weather.name}! ${weatherSort}: ${weatherInfo}`;
headLocationText = `The City of ${basicLocation}`;
}
});
}
// Flickr API
function filckrSearch(){
// Create a new Flickr Client
var flickr = new Flickr(apiKeyFlickr);
// Search Flickr based on latitude and longitude of city
flickr.photos.search({
lat: latLocation,
lon: longLocation,
radius: 20, // Set radius to 20km
sort: flickrsort // Sort the photos by users selection
}).then(function (res) {
var farmid = res.body.photos.photo[0].farm;
}).catch(function (err) {
console.error('bonk', err); // Catch errors
});
}
答案 0 :(得分:1)
这是您如何“承诺” weatherSearch
的部分示例。另一个基本概念相同...将两者都包含进来是多余的。
// Main Page
app.post('/', async function (req, res) {
city = req.body.city; // Grab the users input city
//console.log(weatherSort); // Debugging
try {
let { weatherText, headLocationText } = await weatherSearch(); // Openweather API
await filckrSearch(); // <- promisify the same as above
res.render('index', { weather: weatherText, headlocation: headLocationText, lat: latLocation, long: longLocation, imgLinks: imageLinks, WebLinks: websiteLinks, imgLinksFl: imageLinksFlick, restLat: latitudeRest, restLong: longitudeRest, restname: restName, error: null });
} catch (e) {
// do something if you get an error
}
});
// Weather function
function weatherSearch() {
// API URL
let urlw = `http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${apiKeyWeather}`
// Send out a request
return new Promise((resolve, reject) => {
request(urlw, function (err, response, bodyW) {
// Check for errors
if (err || (JSON.parse(bodyW).cod == '404') || (JSON.parse(bodyW).cod == '401')) {
// If errors are found initialize all variables to empty so that it protects from future errors
// in other API functions
reject(err);
} else {
let weather = JSON.parse(bodyW) // Get JSON result
weatherText = `It's ${weather.main.temp} degrees in ${weather.name}! ${weatherSort}: ${weatherInfo}`;
headLocationText = `The City of ${basicLocation}`;
resolve({ weather, weatherText, headLocationText });
}
});
});
}
基本前提是:
async
/ await
,也可以使用.then()
和.catch()
。 答案 1 :(得分:1)
您的weatherSearch
和flickrSearch
函数都是异步执行的,但方式不同。 weatherSearch
正在发出网络请求,然后在回调中更新文本全局变量。 flickrSearch
也在发出网络请求,但正在通过Promise API处理响应。
您的快速路由代码存在问题,因为它不能编写为处理您在weatherSearch
和flickrSearch
中调用的异步代码。解决此问题的最简单方法是删除要在函数中更新的全局变量,并让它们返回通过网络请求检索的值。这是一个简单的示例:
// Main Page
app.post('/', async function (req, res) {
const weatherResults = await weatherSearch(); // Here we 'await' the response before rendering the HTML
res.render('index', {
weather: weatherResults.weatherText,
headlocation: weatherResults.headLocationText
});
});
// Weather function
async function weatherSearch() {
let urlw = `http://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=${apiKeyWeather}`
return new Promise(function (resolve, reject) {
request(url, function (error, res, body) {
if (err || (JSON.parse(bodyW).cod == '404') || (JSON.parse(bodyW).cod == '401')){
// This is how the Promise API 'returns' an error on failure
reject();
}
else {
let weather = JSON.parse(bodyW)
// This is how the Promise API 'returns' a value on success
resolve({
weatherText: `It's ${weather.main.temp} degrees in ${weather.name}! ${weatherSort}: ${weatherInfo}`,
headLocationText: `The City of ${basicLocation}`
})
}
});
});
}
了解节点中的异步代码非常重要!有很多关于Promises,异步等待和回调的出色文章,您可以用来熟悉它。
答案 2 :(得分:0)
尝试使用BlueBird真的很容易,并且您会在文档中找到很多示例。