0

The code will process an array of calls from darkForecastAPIArray[] which go into the $.getJSON() but it will only return a single callback after processing the other calls indexed into the $.getJSON(). So after the code block is done I cannot get each instance of API requests into the array where it says APIResults.push(), it finishes the calls before it reaches the array and then it leaves only one callback on return. Any suggestions how to get all calls from the "result" into the following APIResults[] array? The whole script works somewhat like a form of indexing multiple JSON pages then placing them into an array to read each page of JSON. To simplify it appears to be finishing the $.getJSON method scope then do the callback once.

$.each(numDaysAPITimes, function(a, time) {
    darkForecastAPIArray.push(darkForecastAPI = /*"http://api.wunderground.com/api/" + currentAPIKey + "/history_" + time + "/q/" + state + "/" + city +".json?callback=?"; */
        "http://api.forecast.io/forecast/" + currentAPIKey + "/" + city + time + "?callback=?");
    console.log(darkForecastAPI);
});
//https://api.forecast.io/forecast/APIKEY/LATITUDE,LONGITUDE,TIME
//$.each(darkForecastAPIArray, function(b, APICallRequest) {
    var deferreds = $.map(darkForecastAPIArray, function(url, index) {
        return $.getJSON(url, {
            tags: "WxAPI[" + index + "]",
            tagmode: "any",
            format: "json"
        });
    });
    $.when.apply($, deferreds).then(function(results) {
        $.each(results, function(index, data) {
            // do something

    APIResults.push(data);
    console.log(index);
    console.log(data);

        for (c = 0; c <= data.daily.data.length - 1; c += 1) {
            if (data.daily.data[c].precipIntensity >= 0.0000 && data.daily.data[c].precipType === "rain") /*Number(result.history.dailysummary.precipm, result.history.dailysummary.rain*/ {
                eachPrecipSum = data.daily.data[c].precipIntensity;
                totalPrecipSinceDate = eachPrecipSum + totalPrecipSinceDate; ///Write mean precip
                alert(Math.round(eachPrecipSum * 10000) / 10000);
                $("body").append("p").text("There has been as least a total of " + Math.round(totalPrecipSinceDate * 10000) / 10000 + " inches per hour of rain at the location in the last " + userDataDatePick + " days");

            } else if (data.daily.data[c].precipIntensity >= 0.0000 && data.daily.data[c].precipType !== "rain") {
                alert("There is was no rain on ____" /*+ result.history.dailysummary.mon + "/" + result.history.dailysummary.mday + "/" + result.history.dailysummary.year*/ );
              }
        }
    });
         });

numDaysAPITimes = 0;
}
safron6
  • 149
  • 1
  • 2
  • 13
  • I would recommend looking in to jQuery deferreds and [$.when](https://api.jquery.com/jquery.when/) - or, what you could do is keep a count of json loaded/failed and when it reaches the length of your url array then call a method to go over each API Result, instead of on each callback since you are appending results each time. – lemieuxster May 07 '15 at 04:14
  • http://stackoverflow.com/questions/6538470/jquery-deferred-waiting-for-multiple-ajax-requests-to-finish – lemieuxster May 07 '15 at 04:16
  • I have looked into $.When some and deferreds. I am not experienced much with either, When I did `$.when.apply($, [APIcollection]).then(function(results))` it would still yield one correct array then make three others after putting them in a `collection.push($.getJSON())`. The deferreds are a little complicated. I am not sure how those work and have not found a decent example to explain it yet. – safron6 May 07 '15 at 04:19
  • I did this before: ` JSONAPIS.push($.getJSON(darkForecastAPI, { tags: "WxAPI[" + i + "]", tagmode: "any", format: "json", })); }); $.when(JSONAPIS).done(function(result) {` – safron6 May 07 '15 at 04:22
  • when you do it that way you need to do a couple things. First, try `$.when.apply($, JSONAPIS) //...` and then expect that your `arguments` list passed to the done function will have one entry for each ajax item you loaded. This can be seen in the examples on https://api.jquery.com/jquery.when/ – lemieuxster May 07 '15 at 04:28
  • I edited my code sample. It currently gets only one correct array object as before. It seems to finish the scope where it says $.getJSON() first then add the callback/when function with one.... still thinking. – safron6 May 07 '15 at 04:38

2 Answers2

1

You are on the right track in your comment about using this recipe. Something like this should work:

var deferreds = $.map(urlArray, function(url, index) {
    return $.getJSON(url, {
        tags: "WxAPI[" + index + "]",
        tagmode: "any",
        format: "json"
    });
});
$.when.apply($, deferreds).then(function(results) {
    $.each(results, function(index, data) {
         // do something
    });
 });
Community
  • 1
  • 1
jtg
  • 386
  • 1
  • 5
  • The data parameter in this $.each callback is your callResult above, so I don't think you need your "$.each(APIResults...)" call. – jtg May 07 '15 at 04:53
  • Do you think I could bypass the $.getJSON statement entirely and use a when with the API_URLs then return the JSON? There is no other way to format JSON to a variable context? – safron6 May 07 '15 at 04:55
  • I tried what you said. I will edit my post again. The result was one correct dataset then a "success" object followed by an array object full of references to the obejct but not the API call data. – safron6 May 07 '15 at 05:01
  • By API call data, do you mean the list of urls? You want to match those to the results? You could "zip(darkForecastAPIArray, results)" where zip is something like this: https://stackoverflow.com/questions/4856717/javascript-equivalent-of-pythons-zip-function – jtg May 07 '15 at 05:07
  • Or just to darkForecastAPIArray[index] in this case. – jtg May 07 '15 at 05:08
  • I meant the JSON that returns from the $.getJSON(//with API url) result. IS zip a custom function then? Would this be a callback?.... I am sorry I need to turn in for the night and will continue tomorrow. – safron6 May 07 '15 at 05:12
  • results should be an array of the json returned by each $.getJSON call. – jtg May 07 '15 at 05:15
  • Yes. But I get the $.getJSON() success object and another one I don't know what with the results array which is meant for the JSON. I will have to think about the zip() method tomorrow. – safron6 May 07 '15 at 05:17
  • This is an idea: `var deferreds = $.map(darkForecastAPIArray, function(url, index) { return $.getJSON(url, { tags: "WxAPI[" + index + "]", tagmode: "any", format: "json" }); }); for(f = 0; f <= deferreds.length - 1; f += 1) { $.when.apply(deferreds[f]).then(function(result) { console.log(result); $.each(results, function(index, data) { // do something` – safron6 May 08 '15 at 00:03
  • Added a `for()` loop to try to get each deferred to process in the `$.when.apply().done()` but it gives me some issues like "undefined". Do you think this could be made to work? – safron6 May 08 '15 at 00:04
0

SOLUTION: Instead of using the loops that come with basic computer snippets I made a function level for() loop to solve the problem and broke the sections of code down into several functions. The functional level for() loop increments as each API call was made until it meets the number of elements. The function I simply named function done() {} The typical for() loop will terminate at its given scope so this one is unique and integrates the multiple callbacks which otherwise could not be used by using an array or deferred since deferreds or $.when() does not return multiple form arrays properly but with extraneous information that is hard to parse out. Here is the code:

function searchRainPrecip() {

            //.......more code........//

    $.each(numDaysAPITimes, function(a, time) {
        darkForecastAPIArray.push(darkForecastAPI = /*"http://api.wunderground.com/api/" + currentAPIKey + "/history_" + time + "/q/" + state + "/" + city +".json?callback=?"; */
            "http://api.forecast.io/forecast/" + currentAPIKey + "/" + city + time + "?callback=?");
     //   console.log(darkForecastAPI);
    });
    //https://api.forecast.io/forecast/APIKEY/LATITUDE,LONGITUDE,TIME
          getDataCallbackResults();
    }


function getDataCallbackResults() { //call this function in loop for each call
    console.log(darkForecastAPIArray[z]);
    console.log(z);
    APIinstance = darkForecastAPIArray[z];
    $.getJSON(APIinstance, {
            tags: "WxAPI[" + f + "]", //Is this tag the name of each JSON page? I tried to index it incase this is how to refer to the JSON formatted code from the APIs.
            tagmode: "any",
            format: "json"
        },
        function(results) {
        APIResults.push(results);
        console.log(results.daily.data.length);
          processAPIPage(results);

        });       
}

function processAPIPage(results) {
            for (c = 0; c <= results.daily.data.length - 1; c += 1) {
                if (results.daily.data[c].precipIntensity >= 0.0000 && results.daily.data[c].precipType === "rain" && results.daily.data[c].time <= unixEpoch) /*Number(result.history.dailysummary.precipm, result.history.dailysummary.rain*/ {
                    eachPrecipSum = results.daily.data[c].precipIntensity;
                    console.log(eachPrecipSum);
                    totalPrecipSinceDate = eachPrecipSum + totalPrecipSinceDate; ///Write mean precip
                    alert(Math.round(eachPrecipSum * 10000) / 10000);
                    d = new Date(results.daily.data[c].time * 1000); //Convert to UTC  ~ SAVE FOR OTHER API SERVICES THAT USE UTC ~
                    curr_date = ("0" + d.getDate()).slice(-2);
                    curr_month = ("0" + (d.getMonth() + 1)).slice(-2); //Months are zero based
                    curr_year = d.getFullYear();
                    console.log(d.getMonth());

                    $("body").append("p").text("There has been as least a total of " + Math.round(totalPrecipSinceDate * 10000) / 10000 + " inches per hour of rain at the location in the since " + curr_month.toString() + "/" + curr_date.toString() + "/" + curr_year.toString());

                } else if (results.daily.data[c].time > unixEpoch) {
                    console.log(results.daily.data[c].time + " > " + unixEpoch);
                } else if (results.daily.data[c].precipIntensity >= 0.0000 && results.daily.data[c].precipType !== "rain" && results.daily.data[c].time <= unixEpoch) {
                    //Also can be named backDateEpochTime to convert next line; Get each day (UNIX seconds)
                    d = new Date(results.daily.data[c].time * 1000); //Convert to UTC  ~ SAVE FOR OTHER API SERVICES THAT USE UTC ~
                    curr_date = ("0" + d.getDate()).slice(-2);
                    curr_month = ("0" + (d.getMonth() + 1)).slice(-2); //Months are zero based
                    curr_year = d.getFullYear();
                    console.log(d.getMonth());

                    alert("There is was no rain on " + curr_month.toString() + "/" + curr_date.toString() + "/" + curr_year.toString());
                }
            }

    numDaysAPITimes = 0;
    result = null;
    done();
}

function done(){
//Global Function level for() loop or get point loops
    z += 1;
    if (z <= darkForecastAPIArray.length-1)
    {
    getDataCallbackResults()
    }
    else
    {
    console.log("All calculations complete.");
    }
}
safron6
  • 149
  • 1
  • 2
  • 13