0

In this project I try to use a url in Javascript in main php to Ajax to a backend php call getWeather.php. And it will get the data from the url and return it to Javascript However I keep losing variable (undefined) after Ajax post. So I print out the result to see, and I found out the Ajax return value is not finish yet when I try to assign the php return result to a Javascript variable.

In my script when a button is click:

 function post (inputString) {
        var result;
        var url ="http://api.openweathermap.org/data/2.5/weather?lat=42.5559287&lon=-92.84954249999998&lang=en&units=metric&appid=MY_API_KEY";

        $.post("getWeather.php",
        {
            postData: url,
        },
        function(data, status){
            alert("Data: " + data + "\nStatus: " + status);
            // console.log("Data: " + data + "\nStatus: " + status);
            //CONSOLE #1
            console.log("url Input: \n" + url + " \n\ndata : \n" + data);
            result = data;
        });
        //CONSOLE #2
        console.log("url Input: \n" + url + " \n\nResult : \n" + result);
    }

And in PHP where the postData is get:

    $s = $_REQUEST['postData'];
echo getWeather_PHP($s);

function getWeather_PHP($url) {
    $contents = file_get_contents($url);
    $clima=json_decode($contents);
    $temp_max=$clima->main->temp_max;
    $temp_min=$clima->main->temp_min;
    $icon=$clima->weather[0]->icon.".png";
    //how get today date time PHP :P
    $today = date("F j, Y, g:i a");
    $cityname = $clima->name; 
    $date =  $cityname . " - " .$today . "<br>";
    $max = "Temp Max: " . $temp_max ."&deg;C<br>";
    $min =  "Temp Min: " . $temp_min ."&deg;C<br>";
    $output = $date." ".$max." ".$min;
    $output = (string)$output;
    // echo $output;
    return $output;
}

Finally the result is : Finally the result is : ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //CONSOLE #2 url Input: http:/..........

Result : undefined

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//CONSOLE #1 ajaxTest.php:24 url Input: http:/..........

data : Aplington - October 1, 2018, 8:12 pm Temp Max: 13.9c Temp Min: 12c

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So CONSOLE #2 completed earlier than CONSOLE #1 So it seem the bug that I cannot get result correctly ??? How do I solve that? Or is there any papular way to do the same thing?

Thank you for helping

M.H
  • 21
  • 4
  • It appears that your `result` is only available within the callback of your AJAX request. – AndrewSteinheiser Oct 01 '18 at 20:32
  • Console 2 will definitely happen before console 1. Console 1 runs after the PHP server responds, and console 2 runs before it gets back. Anything that you need to do with the result of an Ajax request needs to be done from that callback function (containing console 1 right now). – sadq3377 Oct 01 '18 at 20:33
  • You order a pizza and as soon as you hang up the phone, you try to eat the pizza and eat nothing. (console 1). You order the pizza, you wait by your front door until it is delivered, the doorbell rings, you get the pizza and eat it. (console 2) Welcome to the world of asynchronous methods. – epascarello Oct 01 '18 at 20:41

2 Answers2

1

Ajax is asynchronous. That means that code execution continues without waiting for the response, and thus the expected behavior of CONSOLE #2 firing before CONSOLE #1. The callback function passed to the $.post is going to be fired after the request has finished, and you should use it to do anything depending on the data that's supposed to be received from the request. Also it's a good idea to add some error handling in case the request fails for any reason. Also you can now use promises with $.post which might help you chain multiple requests and handle all the errors easily. more details on -> https://api.jquery.com/jquery.post/

Velimir Tchatchevsky
  • 2,812
  • 1
  • 16
  • 21
0

Try turning your AJAX function into a promise. This way you can execute the AJAX request, wait to get the data, then use it somewhere else in your code.

var promise = $.post("getWeather.php").done(function(data, err) {
  return data;
});

promise.then(function(data) {
  console.log(data)
});