我怎样才能让jQuery执行同步而不是asynchronous的Ajax请求?
我有一个提供标准扩展点的JavaScript小部件。 其中之一是beforecreate
function。 它应该返回false
以防止创build项目。
我已经使用jQuery将Ajax调用添加到此函数中:
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); }); }
但是我想阻止我的小部件创build项目,所以我应该在母函数中返回false
,而不是在callback中。 有没有办法使用jQuery或任何其他API执行同步的Ajax请求?
从jQuery文档 :您指定asynchronous选项为false以获得同步Ajax请求。 然后,您的callback可以设置一些数据之前,你的母亲function进行。
如果按照build议进行更改,则代码如下所示:
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 }); }
您可以通过调用将jQuery的Ajax设置设置为同步模式
jQuery.ajaxSetup({async:false});
然后使用jQuery.get( ... );
执行Ajax调用jQuery.get( ... );
然后再打开一次
jQuery.ajaxSetup({async:true});
我想它和@Adam的build议是一样的,但是对于那些想要将jQuery.get()
或jQuery.post()
重新configuration成更复杂的jQuery.ajax()
语法的人来说,这可能会有帮助。
优秀的解决 我注意到,当我试图实现它,如果我在成功的条款中返回一个值,它返回未定义。 我不得不把它存储在一个variables,并返回该variables。 这是我想出的方法:
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; }
所有这些答案都错过了使用async:false执行Ajax调用将导致浏览器挂起,直到Ajax请求完成。 使用stream量控制库将解决这个问题,而不会挂断浏览器。 这是一个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(); }
function getURL(url){ return $.ajax({ type: "GET", url: url, cache: false, async: false }).responseText; } //example use var msg=getURL("message.php"); alert(msg);
请记住,如果您正在进行跨域Ajax调用(通过使用JSONP ) – 不能同步执行,则async
标志将被jQuery忽略。
$.ajax({ url: "testserver.php", dataType: 'jsonp', // jsonp async: false //IGNORED!! });
对于JSONP调用,您可以使用:
- Ajax调用你自己的域名 – 并进行跨域调用服务器端
- 改变你的代码asynchronous工作
- 使用“函数音序器”库像Frame.js(这个答案 )
- 阻止用户界面,而不是阻止执行(这个答案 )(我最喜欢的方式)
注意:你不应该使用async:
从Gecko 30.0(Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)开始,由于对用户体验的负面影响,主线程上的同步请求已被弃用。
Chrome甚至在控制台中对此提出警告:
主线程上的同步XMLHttpRequest由于对最终用户的体验有不利的影响而被弃用。 如需更多帮助,请查看https://xhr.spec.whatwg.org/ 。
这可能会打破你的网页,如果你正在做这样的事情,因为它可能会停止工作的任何一天。
如果你想这样做,仍然觉得,如果它是同步的,但仍然不阻止,那么你应该使用asynchronous/等待,也可能还有一些基于承诺的ajax,如新的Fetch API
async function foo() { var res = await fetch(url) console.log(res.ok) var json = await res.json() console.log(json) }
我使用了Carcione给出的答案,并将其修改为使用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'); } }
我添加了“json”的dataType并将.responseText更改为responseJSON 。
我也使用返回对象的statusText属性检索状态。 请注意,这是Ajax响应的状态,而不是JSON是否有效。
后端必须以正确的(格式良好的)JSON返回响应,否则返回的对象将是未定义的。
回答原来的问题时要考虑两个方面。 一个是告诉Ajax同步执行(通过设置async:false ),另一个通过调用函数的return语句返回响应,而不是callback函数。
我也试过用POST,它的工作。
我将GET更改为POST并添加了数据: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; }
请注意,上述代码仅适用于async为false的情况。 如果要设置async:true,那么返回的对象jqxhr在ajax调用返回时不会有效,只是在稍后asynchronous调用完成时才会生效,但是设置响应variables为时已晚。
与async: false
你让自己被阻止的浏览器。 对于非阻塞同步解决scheme,您可以使用以下方法:
ES6 / ECMAScript2015
有了ES6,你可以使用一个发生器和co库 :
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
有了ES7,你可以使用asyc等待:
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 })(); }
这是例子:
$.ajax({ url: "test.html", async: false }).done(function(data) { // Todo something.. }).fail(function(xhr) { // Todo something.. });
JavaScript客户端代码
function isValidLogin() { var flag = false; var Response = $.ajax({ type: "POST", dataType: "json", contentType: "application/json; charset=utf-8", url: "UPSLabelFormCA.aspx/IsValidLogin", async: false }).responseText; var toJson = jQuery.parseJSON(Response); if (toJson.d[0].Message == 'SUCCESS') { flag = true; } return flag; }
ASP.NET服务器端代码
[WebMethod] public static List<ShipInfo> IsValidLogin() { List<ShipInfo> loginStatus = new List<ShipInfo>(); if (HttpContext.Current.User.Identity.IsAuthenticated && HttpContext.Current.Session["Email"] != null) { loginStatus.Add(new ShipInfo() { Success = true, Message = "SUCCESS" }); } else { loginStatus.Add(new ShipInfo() { Success = false, Message = "FAILED" }); } return loginStatus; }
首先,我们应该了解何时使用$ .ajax以及何时使用$ .get / $。post
当我们需要对ajax请求进行低级别的控制时,比如请求头部设置,caching设置,同步设置等。那么我们应该去$ .ajax。
$ .get / $。post:当我们不需要对ajax请求进行低级别的控制时,只需要简单地获取/发布数据到服务器。 这是速记
$.ajax({ url: url, data: data, success: success, dataType: dataType });
因此我们不能使用$ .get / $。post的其他function(同步,caching等)。
因此,对于ajax请求的低级控制(sync,cache等),我们应该去$ .ajax
$.ajax({ type: 'GET', url: url, data: data, success: success, dataType: dataType, async:false });