0

所以我试图在 JavaScript 中运行一个函数,但我需要在该函数开始之前运行并完成所有其他函数。这是代码(对不起,我知道它很长,但这是我可以说明正在发生的事情的唯一方法):

        getWeather();
        getAverage();


function getWeather() {
    $.getJSON("http://where.yahooapis.com/geocode?q=" + lat + ",+" + lon + "&gflags=R&flags=J", function(data){
        zipCode = data.ResultSet.Results[0].postal;
        zipCode = zipCode.substring(0,5);
        WOEID = data.ResultSet.Results[0].woeid;
        getYahooWeather(WOEID);
        getWeatherbug(zipCode);
        getWeatherUnderground(zipCode);
        getWorldWeather(zipCode);
    });
}

function getYahooWeather(x) {
    var query = escape('select item from weather.forecast where woeid="'+x+'"');
    var url = "http://query.yahooapis.com/v1/public/yql?q=" + query + "&format=json";


    $.getJSON(url, function(data2){
        yahooTemp = data2.query.results.channel.item.condition.temp;
        $("#yahoo-weather p").replaceWith("<p>Weather from Yahoo! powered by The Weather Channel = "+yahooTemp+"&deg;F</p>");
    });
}

function getWeatherbug(x) {
    var url = "http://i.wxbug.net/REST/Direct/GetObs.ashx?api_key="+ weatherbugAPI + "&zip="+x+"&ht=t&ic=1&f=?";
    console.log(url);

    $.ajax({
        url: url,
        dataType: "jsonp",
        success: function(data3) {
            //console.log(data3.temperature);
            wbTemp = data3.temperature;
            $("#wb-weather p").replaceWith("<p>Weather from WeatherBug = "+wbTemp+"&deg;F</p>");
        }
    });
}

function getWeatherUnderground(x) {
    $.ajax({
    url: "http://api.wunderground.com/api/b87325296cd69fa8/geolookup/conditions/q/IA/"+x+".json",
    dataType: "jsonp",
    success: function(parsed_json) {
        var location = parsed_json['location']['city'];
        wuTemp = parsed_json['current_observation']['temp_f'];
        $("#wu-weather p").replaceWith("<p>Weather from Weather Underground = "+wuTemp+"&deg;F</p>");
        }
    });
}

function getWorldWeather(x) {
    var url = "http://free.worldweatheronline.com/feed/weather.ashx?key="+wwKey+"&q="+x+"&fx=no&format=json";

    $.ajax({
        url: url,
        dataType: "jsonp",
        success: function(data6) {
            wwTemp = data6.data.current_condition[0].temp_F;
            $("#ww-weather p").replaceWith("<p>Weather from World Weather Online = "+wwTemp+"&deg;F</p>");
        }
    });
}

function getAverage() {
    avTemp = wbTemp + wwTemp + yahooTemp + wuTemp;
    console.log(avTemp);
}

我遇到的问题是,每当我运行 getAverage 函数时,它都会返回 NaN,因为其他函数还没有返回它们的数据。

有没有办法在所有以前的函数返回它们的数据之后运行一个函数?

谢谢

4

3 回答 3

3

一种更简单的方法是使用async可以在https://github.com/caolan/async找到的异步库。您可以使用该parallel函数并行运行 getter,然后在所有 getter 完成后返回。代码最终看起来像:

async.parallel([
    function(callback){
        setTimeout(function(){
            callback(null, 'one');
        }, 200);
    },
    function(callback){
        setTimeout(function(){
            callback(null, 'two');
        }, 100);
    },
],
// optional callback
function(err, results){
    // the results array will equal ['one','two'] even though
    // the second function had a shorter timeout.
});

另一种方法是拥有一个包含您正在等待的回调数量的全局变量。然后在每个天气获取器的回调中,递减计数器。在取平均值之前,只需等到计数器为 0 即可(您可以使用 setTimeout 等待一定时间,然后再次检查)。

于 2012-04-30T03:54:51.980 回答
1

简而言之:getAveragegetJSON回调中调用,即在你调用getWorldWeather(zipCode);.

于 2012-04-30T03:52:00.253 回答
0

肯定有。您将需要执行所谓的方法传递或回调。

这是一个未经测试的示例,说明您将如何去做:http: //jsfiddle.net/UDbeV/

让我更详细地解释一下。

var i = 0;
loopCount = function() {
    i++;
    if (i > 5) {
        getAverage();
    }
});

所以我们正在创建一个名为 loopCount 的函数来存储一个计数器。每次调用时,我们将其计数器加 1。

让我们将回调传递给您的方法:

    getYahooWeather(WOEID, callback);
    getWeatherbug(zipCode, callback);
    getWeatherUnderground(zipCode, callback);
    getWorldWeather(zipCode, callback);
    callback();

现在我们必须更改函数以允许第二个参数:

function getYahooWeather(x, callback) { ...

最后,在每个块的末尾,我们要调用它:

$.getJSON(url, function(data2) {
    yahooTemp = data2.query.results.channel.item.condition.temp;
    $("#yahoo-weather p").replaceWith("<p>Weather from Yahoo! powered by The Weather Channel = " + yahooTemp + "&deg;F</p>");
    callback();
});

回调检查“它是否被调用了足够的次数(即:从平均之前你做了多少次调用),然后调用 getAverage();

可能有更有效的方法可以做到这一点,但它是星期一 :P 而且,它未经测试,所以如果你使用它,你可能需要稍微修改一下。:o)

于 2012-04-30T04:11:47.443 回答