如何让 jQuery 执行同步的而不是异步的 Ajax 请求?

I have a JavaScript widget which provides standard extension points. One of them is the beforecreate function. It should return false to prevent an item from being created.

I've added an Ajax call into this function using jQuery:

beforecreate: function (node, targetNode, type, to) {
  jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),

  function (result) {
    if (result.isOk == false) 
        alert(result.message);
  });
}

But I want to prevent my widget from creating the item, so I should return false in the mother-function, not in the callback. Is there a way to perform a synchronous AJAX request using jQuery or any other in-browser API?

转载于:https://stackoverflow.com/questions/133310/how-can-i-get-jquery-to-perform-a-synchronous-rather-than-asynchronous-ajax-re

csdnceshi62
csdnceshi62 This question is like asking "how do I store my user passwords in plain text?" Sure there is an answer, but don't do it.
接近 2 年之前 回复
csdnceshi65
larry*wei You can try using embeddedjs.com
大约 2 年之前 回复
csdnceshi56
lrony* If people ask me for 1 piece of advice when starting javascript, I say: embrace the asynchronous character of javascript, don't try ty fight that.
接近 3 年之前 回复
csdnceshi66
必承其重 | 欲带皇冠 is spot on. Sync XHR is not required here
大约 4 年之前 回复
weixin_41568174
from.. I propose the Sajak function. Do we have a letter T? Yes vanna, give me 3 T's.
4 年多之前 回复
csdnceshi71
Memor.の The proper way to solve that would be to rewrite your widget's extension point use promises. This way would easily allow you to set up an asynchronous action (like an ajax request) as beforecreate.
接近 7 年之前 回复

13个回答

From the jQuery documentation: you specify the asynchronous option to be false to get a synchronous Ajax request. Then your callback can set some data before your mother function proceeds.

Here's what your code would look like if changed as suggested:

beforecreate: function (node, targetNode, type, to) {
    jQuery.ajax({
        url: 'http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value),
        success: function (result) {
            if (result.isOk == false) alert(result.message);
        },
        async: false
    });
}
csdnceshi54
hurriedly% please check this question also stackoverflow.com/questions/51112102/…
2 年多之前 回复
weixin_41568183
零零乙 Not true. As of this comment, the official docs still don't list it as deprecated, and it works without generating a warning. See this fiddle
2 年多之前 回复
weixin_41568131
10.24 Important to note async: false option is deprecated for newer versions of jQuery > 3.0 . Thus, this method is not implementable.
2 年多之前 回复
csdnceshi62
csdnceshi62 : no, see Ben Johnson's comment. It's been deprecated in conjunction with $.Deferred, not by itself.
接近 3 年之前 回复
csdnceshi73
喵-见缝插针 async is deprecated
大约 3 年之前 回复
csdnceshi65
larry*wei Is it safe to use Async:False, Because it will hold the execution of rest code. Once you get response of ajax, only then, rest of the code will execute. What is good way to handle if server does not response to Ajax request? should i add timeout to continue other request if server does not response to Ajax request?
大约 3 年之前 回复
csdnceshi58
Didn"t forge async: false is still supported in jQuery >= 1.8. The ability to use async: false with jqXHR ($.Deferred) is what was deprecated. In other words, one must use the newer success/error/complete callback options, instead of the legacy methods, e.g., jqXHR.done().
接近 5 年之前 回复
csdnceshi80
胖鸭 async false is no longer supported for jQuery >= 1.8. Refer to api.jquery.com/jQuery.ajax
大约 5 年之前 回复
weixin_41568174
from.. just a note, adding the async:false works great for me, as long as I set the entire ajax function as the value of some variable. for example, var ajaxresults = $.ajax({....
7 年多之前 回复
weixin_41568126
乱世@小熊 my comment is aimed at SLA80's incorrect comment; it is possible to use get(), post(), load() for synchronous calls.
8 年多之前 回复
csdnceshi55
~Onlooker the answer is still correct, and relevant if you only want only certain requests to be synchronous.
8 年多之前 回复
weixin_41568126
乱世@小熊 Nope. Since jQuery 1.1: stackoverflow.com/questions/6849686/…
大约 9 年之前 回复
csdnceshi70
笑故挽风 Exactly, it is impossible to use get(), post(), load() for synchronous calls. Only ajax() have "async" parameter, which can be set to "false".
10 年多之前 回复

You can put the jQuery's Ajax setup in synchronous mode by calling

jQuery.ajaxSetup({async:false});

And then perform your Ajax calls using jQuery.get( ... );

Then just turning it on again once

jQuery.ajaxSetup({async:true});

I guess it works out the same thing as suggested by @Adam, but it might be helpful to someone that does want to reconfigure their jQuery.get() or jQuery.post() to the more elaborate jQuery.ajax() syntax.

weixin_41568134
MAO-EYE Shouldn't be set globally..
接近 4 年之前 回复
weixin_41568127
?yb? At least, this is the best bad idea. instead of saying: "THERE IS NO WAY EXCEPT $.ajax()". ;)
4 年多之前 回复
csdnceshi69
YaoRaoLov This is a really bad idea, why would you set it at a global level? And then be forced to unset it after?
大约 6 年之前 回复

Excellent solution! I noticed when I tried to implement it that if I returned a value in the success clause, it came back as undefined. I had to store it in a variable and return that variable. This is the method I came up with:

function getWhatever() {
  // strUrl is whatever URL you need to call
  var strUrl = "", strReturn = "";

  jQuery.ajax({
    url: strUrl,
    success: function(html) {
      strReturn = html;
    },
    async:false
  });

  return strReturn;
}
weixin_41568183
零零乙 This is a Synchronous call (async:false).
8 年多之前 回复
weixin_41568196
撒拉嘿哟木头 this is absolutely wrong. You can't be sure that an asynchronous call has finished when returning 'strReturn'.
8 年多之前 回复
csdnceshi54
hurriedly% That's because you were returning a value out of the callback, not out of getWhatever. Thus you returned nothing i.e. undefined from your getWhatever.
9 年多之前 回复
function getURL(url){
    return $.ajax({
        type: "GET",
        url: url,
        cache: false,
        async: false
    }).responseText;
}


//example use
var msg=getURL("message.php");
alert(msg);
csdnceshi78
程序go I don't see that this answer has anything to offer, it's just the accepted answer wrapped into a function and answered four years later. It's a bad thing to advise people to C+P, because the function does not indicate what it does. "So getURL vs get ? why does one hang my browser?" etc.
大约 4 年之前 回复
csdnceshi61
derek5. What is the way to perform a synchronous ajax call using jQuery without use the main thread?
4 年多之前 回复
weixin_41568196
撒拉嘿哟木头 Note that though, you might get this: 'Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.'
5 年多之前 回复

Note: You shouldn't use async due to this:

Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.

Chrome even warns about this in the console:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.

This could break your page if you are doing something like this since it could stop working any day.

If you want to do it a way that still feels like if it's synchronous but still don't block then you should use async/await and probably also some ajax that is based on promises like the new Fetch API

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}
weixin_41568174
from.. the function foo has been converted to a promise by just using the word async in the beginning, so you could just do foo().catch(...) to catch it also
3 年多之前 回复
weixin_41568127
?yb? Note that you should wrap your await fetch(url) call in a try... catch block to catch any asynchronous errors.
3 年多之前 回复

With async: false you get yourself a blocked browser. For a non blocking synchronous solution you can use the following:

ES6/ECMAScript2015

With ES6 you can use a generator & the co library:

beforecreate: function (node, targetNode, type, to) {
    co(function*(){  
        let result = yield jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    });
}

ES7

With ES7 you can just use asyc await:

beforecreate: function (node, targetNode, type, to) {
    (async function(){
        let result = await jQuery.get('http://example.com/catalog/create/' + targetNode.id + '?name=' + encode(to.inp[0].value));
        //Just use the result here
    })(); 
}
weixin_41568127
?yb? Notice you can just pass async function to beforecreate beforecreate: async function(.... and remove the self invoked async function
2 年多之前 回复

I used the answer given by Carcione and modified it to use JSON.

 function getUrlJsonSync(url){

    var jqxhr = $.ajax({
        type: "GET",
        url: url,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}    

function testGetUrlJsonSync()
{
    var reply = getUrlJsonSync("myurl");

    if (reply.valid == 'OK')
    {
        console.dir(reply.data);
    }
    else
    {
        alert('not valid');
    }    
}

I added the dataType of 'JSON' and changed the .responseText to responseJSON.

I also retrieved the status using the statusText property of the returned object. Note, that this is the status of the Ajax response, not whether the JSON is valid.

The back-end has to return the response in correct (well-formed) JSON, otherwise the returned object will be undefined.

There are two aspects to consider when answering the original question. One is telling Ajax to perform synchronously (by setting async: false) and the other is returning the response via the calling function's return statement, rather than into a callback function.

I also tried it with POST and it worked.

I changed the GET to POST and added data: postdata

function postUrlJsonSync(url, postdata){

    var jqxhr = $.ajax({
        type: "POST",
        url: url,
        data: postdata,
        dataType: 'json',
        cache: false,
        async: false
    });

    // 'async' has to be 'false' for this to work
    var response = {valid: jqxhr.statusText,  data: jqxhr.responseJSON};

    return response;
}

Note that the above code only works in the case where async is false. If you were to set async: true the returned object jqxhr would not be valid at the time the AJAX call returns, only later when the asynchronous call has finished, but that is much too late to set the response variable.

Keep in mind that if you're doing a cross-domain Ajax call (by using JSONP) - you can't do it synchronously, the async flag will be ignored by jQuery.

$.ajax({
    url: "testserver.php",
    dataType: 'jsonp', // jsonp
    async: false //IGNORED!!
});

For JSONP-calls you could use:

  1. Ajax-call to your own domain - and do the cross-domain call server-side
  2. Change your code to work asynchronously
  3. Use a "function sequencer" library like Frame.js (this answer)
  4. Block the UI instead of blocking the execution (this answer) (my favourite way)

All of these answers miss the point that doing an Ajax call with async:false will cause the browser to hang until the Ajax request completes. Using a flow control library will solve this problem without hanging up the browser. Here is an example with Frame.js:

beforecreate: function(node,targetNode,type,to) {

    Frame(function(next)){

        jQuery.get('http://example.com/catalog/create/', next);
    });

    Frame(function(next, response)){

        alert(response);
        next();
    });

    Frame.init();
}
csdnceshi55
~Onlooker Synchronous calls are handy if you want to put together a quick test harness for a REST back-end and would prefer simplicity over callback hell.
6 年多之前 回复

Firstly we should understand when we use $.ajax and when we use $.get/$.post

When we require low level control over the ajax request such as request header settings, caching settings, synchronous settings etc.then we should go for $.ajax.

$.get/$.post: When we do not require low level control over the ajax request.Only simple get/post the data to the server.It is shorthand of

$.ajax({
  url: url,
  data: data,
  success: success,
  dataType: dataType
});

and hence we can not use other features(sync,cache etc.) with $.get/$.post.

Hence for low level control(sync,cache,etc.) over ajax request,we should go for $.ajax

 $.ajax({
     type: 'GET',
      url: url,
      data: data,
      success: success,
      dataType: dataType,
      async:false
    });
共13条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐