我有这个codepen Localweather App我创建了两个函数。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
$(document).ready(function() {
var city = "Newcastle";
city = getLocation();
//set city to location from function;
console.log ("city undefined?" +city);
//this is undefind, why?
getWeather(city).then(function(data) {
console.log(data);
var weatherType = data.weather[0].description;
var weatherId = data.weather[0].id;
var tempF = Math.round(data.main.temp);
var tempC = Math.round((tempF - 32) / 1.8);
var wind = data.wind.speed;
var name = data.name;
console.log(weatherType);
$('#weather').html(weatherType);
$('#temp').html(tempC + "°C");
$('#wind').html(tempF + "°F");
$('#icon').html(weatherId);
$('#location').html(name);
})
});
function getLocation() {
$.getJSON('http://ipinfo.io', function(data) {
console.log("data" + data);
city = data.city;
console.log("city" + city);
return city;
})
}
function getWeather(place) {
return $.getJSON('http://api.openweathermap.org/data/2.5/weather?q=' + place + '&units=imperial&APPID=90d625c068e3f3d7818b9e4237871e21');
}
</script>
getWeather函数,它接收一个位置并返回该位置的天气对象。我也有一个getLocation函数,我想基于ip返回我的城市(是的,我知道它不准确,但它是我想要使用的)。
如果我对城市进行硬编码,那就有效。 但是尝试使用getLoction函数中的city变量是不行的。 我猜这是与异步有关但我通过在getLoction函数中使用回调它会返回'city',然后'然后'传递给getWeather。 或者我的想法都错了?
答案 0 :(得分:1)
您需要使用(嵌套)回调,因为您需要等待来自AJAX调用的异步响应。
您的浏览器不会等待异步函数完成并继续运行到下一个语句,这就是代码中未定义city的原因 - 因为在代码中getLocation
仅返回{{1}时的值完成。
如果你的函数会像这样,你会得到一个返回值,而不是你想要的那个(所以不要使用下面的代码片段,它只是为了解释)。
getJSON
在下面的示例中,我们将函数作为参数传递给function getLocation() {
$.getJSON('http://ipinfo.io', function(data) {
return data.city; // this will be ignored, because the browser will jump to the next statement
});
return "XXX"; // <- this will be returned, because the browser will not wait for async functions to finish
}
。参数名称为getLocation
,我们在callback
完成后使用data
参数调用此函数。
我们可以从此数据参数中提取$.getJSON('http://ipinfo.io'
,然后调用city
。
请注意getWeather
不再返回任何值,而是将getLocation
参数传递给回调(或者您可以在data
中提取city
然后传递{{ 1}}代替回调。)
getLocation
city
答案 1 :(得分:1)
return city;
中的 getLocation()
仅从传递到function(data)
的匿名函数$.getJSON
返回。您的getLocation
实际上没有return
声明city = undefined
处理此问题的一种方法可能是使用getJSON
承诺:
getLocation().then(function (data) {
console.log(data);
getWeather(data.city).then(...
});
然后getLocation
看起来像:
function getLocation () {
return $.getJSON(...
}
从答案中可以看出,有很多方法可以使用nested callbacks
或Promises
来解决此问题。
答案 2 :(得分:1)
如果要链接AJAX调用,则需要在前一个回调中设置下一个AJAX调用。这样,下一个AJAX调用将仅在前一个AJAX调用完成后发送。
这个答案是一个细微的变化,使用IP地址来获取纬度/经度(而不是城市)&amp;然后将其用于天气。
http://codepen.io/anon/pen/ZOpEBQ
var ip = '8.8.8.8';
$.get('https://ipapi.co/'+ip+'/latlong/', function(data){
data = data.split(',');
console.log(data);
$.get('http://api.openweathermap.org/data/2.5/weather?lat='+data[0]+'&lon='+data[1]+'&units=imperial&APPID=90d625c068e3f3d7818b9e4237871e21', function(data1) {
// Should print the weather
console.log(data1);
});
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
&#13;
答案 3 :(得分:0)
城市仍未定义,因为getWeather
不会等待getLocation
执行并为城市分配值。你总是可以把
$.getJSON('http://ipinfo.io', function(data) {
console.log("data" + data);
city = data.city;
console.log("city" + city);
$.getJSON('http://api.openweathermap.org/data/2.5/weather?q=' + city + '&units=imperial&APPID=90d625c068e3f3d7818b9e4237871e21');
})
或者您可以使用jQuery.Deferred()
对象仅在完成城市时执行获取天气。
答案 4 :(得分:0)
基本上你需要在调用openwheater之前等待ipinfo回调,否则city将是未定义的,这是一个异步调用机制
$(document).ready(function() {
getLocation().then(function(city){
getWeather(city.city).then(function(data) {
console.log(data);
var weatherType = data.weather[0].description;
var weatherId = data.weather[0].id;
var tempF = Math.round(data.main.temp);
var tempC = Math.round((tempF - 32) / 1.8);
var wind = data.wind.speed;
var name = data.name;
console.log(weatherType);
$('#weather').html(weatherType);
$('#temp').html(tempC + "°C");
$('#wind').html(tempF + "°F");
$('#icon').html(weatherId);
$('#location').html(name);
}, function(err){
console.log("ERROR!", err);
})
}, function(err){
console.log("ERROR!", err);
});
});
function getLocation() {
return $.getJSON('http://ipinfo.io');
}
function getWeather(place) {
return $.getJSON('http://api.openweathermap.org/data/2.5/weather?q=' + place + '&units=imperial&APPID=90d625c068e3f3d7818b9e4237871e21');
}