31
function ajax_test(str1){ 
  var url = "None" 
  jq.ajax({
    type:'post', 
    cache: false, 
    url: 'http://....' + str1, 
    success: function(data, status, xhr){ 
      url=data; 
    }, 
    error: function (xhr, status, e) {  
    }, 
    async: true, 
    dataType: 'json' 
  }); 
  return url 
} 

How can I set the global variable url to be the returned success ajax data?

isherwood
  • 58,414
  • 16
  • 114
  • 157
sammiwei
  • 3,140
  • 9
  • 41
  • 53
  • You need to do something with `url` only once the success is thrown? – nicosantangelo Aug 11 '12 at 21:20
  • It's not global, because it has the keyword var in front of it. I think you mean outer scope. – maximus Aug 11 '12 at 21:20
  • Thanks for the prompt replies! @maximus yes outer scope is what i meant. I do have a valid url, I just took out the detail part. – sammiwei Aug 11 '12 at 21:25
  • 1
    If it's relative to your `return` value, the ajax is asynchronous so it'll return the value before the ajax completes. Unless you use synchronous request which happens to be deprecated and may cause unexpected behavior. What version of jQuery are you using btw? There might be an alternative solution. – Fabrício Matté Aug 11 '12 at 21:32
  • jQuery 1.7.2. And yes, I have changed the async to be false, then I get the value from success. – sammiwei Aug 11 '12 at 21:34
  • @FabrícioMatté: According to the docs only the use of async: false with jqXHR ($.Deferred) is deprecated; I think it means you can't specify a callback anymore in `beforeSend()` for example and must use the success/complete/error callback handlers instead. I don't think it means do not use async: false if you simply want to execute the call synchronously. Though, regardless, using a callback is better as it does not lock the browser. – Nope Aug 11 '12 at 21:42
  • @FrançoisWahl Yes, deprecated or not it's still available as long as your build includes the deprecated methods (all currently hosted CDN versions have these). It just means that they generally are not good practice and should be avoided as they may be removed in a future version. Of course, they should be available as deprecated even in future versions if you really need to include those. – Fabrício Matté Aug 11 '12 at 21:45
  • @FabrícioMatté: Sorry, what I meant is that async: false is only depcriated in combination with callbacks in methods other than success/complete/error i.e: `beforeSend`, etc... However async: false by itself does not seem to be deprecated as long as you are only using the callbacks in success/complete/error. – Nope Aug 11 '12 at 21:47
  • 1
    @FrançoisWahl No problem, even the shorthand form selectors (e.g. `:checkbox`) and the `.load()` method are marked as deprecated which I used a lot in the past, I was commenting that `async:false` is usually not good practice for locking up the browser, forget about the deprecation. `:P` – Fabrício Matté Aug 11 '12 at 21:50
  • 1
    @FabrícioMatté: +1, totally agree on good practise. I just found the note on 1.8 changes a little confusing myself :) – Nope Aug 11 '12 at 21:54
  • @FrançoisWahl Oh I went through the whole changelog, only got me even more confused with each line. `=]` – Fabrício Matté Aug 11 '12 at 21:54

2 Answers2

30

In Javascript, it is impossible for a function to return an asynchronous result. The function will usually return before the AJAX request is even made.

You can always force your request to be syncronous with async: false, but that's usually not a good idea because it will cause the browser to lock up while it waits for the results.

The standard way to get around this is by using a callback function.

function ajax_test(str1, callback){  
   jq.ajax({ 
     //... your options
     success: function(data, status, xhr){  
       callback(data);
     }
   });  
}  

and then you can call it like this:

ajax_test("str", function(url) {
  //do something with url
});
Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • This may not be the what OP asked specifically, but it's the right way to do things. +1 – Fabrício Matté Aug 11 '12 at 21:36
  • There's some contradiction in your first 2 paragraphs. It's impossible to return an asynchronous result [unless using `async:false` which should be avoided unless strictly necessary as explained in your second paragraph]. It's well explained enough though. – Fabrício Matté Aug 11 '12 at 21:58
  • @FabrícioMatté No, it's not a contradiction because if you use `async:false`, then it's not asynchronous anymore. – Peter Olson Aug 11 '12 at 22:01
  • Fault made a similar [comment](http://stackoverflow.com/questions/11917734/jquery-ajax-call-success-how-do-i-change-a-global-variable-in-the-wrapper-javas/11917846#comment15868884_11917807) on his answer, but that's a good point. – Fabrício Matté Aug 11 '12 at 22:01
  • Im trying to do this, but I get told the name of my callback function doesn't exist. Every other solution I try to find sends me here – Frank B Feb 19 '16 at 01:59
  • @FrankB I can't diagnose your problem without seeing the code. You can ask a separate question if you need help. – Peter Olson Feb 19 '16 at 07:11
5

Here is my example code for retrieving data from php, and then pass the value to a javascript global variable within ajax success function. It works for me!

var retVal = null; 

function ajaxCallBack(retString){
    retVal = retString;
}

function readString(filename){
    $.ajax({  
        type: "POST",  
        url: "readString.php",  
        data: { 'fn': filename },      
        success: function(response){
            ajaxCallBack(response);
        }
    }); 
}

PHP code (readString.php):

<?php

     $fn  = $_POST['fn'];

     $file = fopen("path/".$fn.".record","r");
     $string = fread($file,filesize("path/".$fn.".record"));
     fclose($file); 

     echo $string;  
?>

However, as $.ajax() sent requests asynchronously, which means it may return before the success callback runs, you should not rely on it runs sequentially and return the value by itself. Therefore, here we assign php response value to global value in callback function.

Terry Tang
  • 191
  • 3
  • 6