提问人:Artem Tikhomirov 提问时间:9/25/2008 最后编辑:Artem Tikhomirov 更新时间:11/16/2020 访问量:825904
如何让jQuery执行同步而不是异步的Ajax请求?
How can I get jQuery to perform a synchronous, rather than asynchronous, Ajax request?
问:
我有一个提供标准扩展点的 JavaScript 小部件。其中之一是功能。它应该返回以防止创建项目。beforecreate
false
我使用 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);
});
}
但是我想阻止我的小部件创建项目,所以我应该在母函数中返回,而不是在回调中返回。有没有办法使用 jQuery 或任何其他浏览器内 API 执行同步 AJAX 请求?false
答:
在 jQuery 文档中:将异步选项指定为 false 以获取同步 Ajax 请求。然后,您的回调可以在母函数继续之前设置一些数据。
以下是如果按照建议进行更改,您的代码将是什么样子:
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
});
}
评论
async: false
"
https://www.taniarascia.com/how-to-promisify-an-ajax-call/
jqxhr
优秀的解决方案!当我尝试实现它时,我注意到,如果我在 success 子句中返回一个值,它就会返回为 undefined。我必须将其存储在变量中并返回该变量。这是我想出的方法:
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;
}
评论
您可以通过调用
jQuery.ajaxSetup({async:false});
然后使用jQuery.get( ... );
然后再次打开一次
jQuery.ajaxSetup({async:true});
我想它的工作原理与@Adam建议的相同,但对于确实想要重新配置或更复杂的语法的人来说,它可能会有所帮助。jQuery.get()
jQuery.post()
jQuery.ajax()
function getURL(url){
return $.ajax({
type: "GET",
url: url,
cache: false,
async: false
}).responseText;
}
//example use
var msg=getURL("message.php");
alert(msg);
所有这些答案都忽略了一点,即使用 async:false 执行 Ajax 调用将导致浏览器挂起,直到 Ajax 请求完成。使用流控制库可以解决这个问题,而无需挂起浏览器。下面是 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();
}
示例如下:
$.ajax({
url: "test.html",
async: false
}).done(function(data) {
// Todo something..
}).fail(function(xhr) {
// Todo something..
});
我使用了 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”的数据类型,并将.responseText更改为responseJSON。
我还使用返回对象的 statusText 属性检索了状态。请注意,这是 Ajax 响应的状态,而不是 JSON 是否有效。
后端必须以正确(格式正确)的 JSON 返回响应,否则返回的对象将未定义。
在回答原始问题时,需要考虑两个方面。一种是告诉 Ajax 同步执行(通过设置 async: false),另一种是通过调用函数的 return 语句返回响应,而不是返回回调函数。
我也用 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 调用返回时无效,只有在异步调用完成后才有效,但这太晚了,无法设置响应变量。
请记住,如果您正在执行跨域 Ajax 调用(通过使用 JSONP) - 您不能同步执行,则 jQuery 将忽略该标志。async
$.ajax({
url: "testserver.php",
dataType: 'jsonp', // jsonp
async: false //IGNORED!!
});
对于 JSONP 调用,您可以使用:
有了你,你就会得到一个被阻止的浏览器。
对于非阻塞同步解决方案,可以使用以下方法:async: false
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
});
}
DSV公司
在 ES7 中,您只需使用 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
})();
}
注意:由于出现以下警告消息,您不应使用:async: false
从 Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27) 开始,由于对用户体验的负面影响,主线程上的同步请求已被弃用。
Chrome 甚至在控制台中对此发出警告:
主线程上的同步 XMLHttpRequest 已被弃用,因为它会对最终用户的体验产生不利影响。如需更多帮助,请查看 https://xhr.spec.whatwg.org/。
如果您正在做这样的事情,这可能会破坏您的页面,因为它随时可能停止工作。
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)
}
Edit chrome is working on Disallowing sync XHR in page dismissal when the page is being navigated away or closed by the user. This involves beforeunload, unload, pagehide and visibilitychange.
if this is your use case then you might want to have a look at navigator.sendBeacon instead
It is also possible for the page to disable sync req with either http headers or iframe's allow attribute
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
});
这是我使用 jQuery 处理 ASYNC 请求的简单实现。我希望这对任何人有所帮助。
var queueUrlsForRemove = [
'http://dev-myurl.com/image/1',
'http://dev-myurl.com/image/2',
'http://dev-myurl.com/image/3',
];
var queueImagesDelete = function(){
deleteImage( queueUrlsForRemove.splice(0,1), function(){
if (queueUrlsForRemove.length > 0) {
queueImagesDelete();
}
});
}
var deleteImage = function(url, callback) {
$.ajax({
url: url,
method: 'DELETE'
}).done(function(response){
typeof(callback) == 'function' ? callback(response) : null;
});
}
queueImagesDelete();
由于不推荐使用同步操作,因此我想出了以下解决方案,该解决方案将 .这允许有序的 AJAX 查询,同时本质上仍然是无菌的,这对于一次性 CSRF 令牌非常有用。XMLHttpReponse
XMLHttpRequest
它也是透明的,因此像jQuery这样的库可以无缝运行。
/* wrap XMLHttpRequest for synchronous operation */
var XHRQueue = [];
var _XMLHttpRequest = XMLHttpRequest;
XMLHttpRequest = function()
{
var xhr = new _XMLHttpRequest();
var _send = xhr.send;
xhr.send = function()
{
/* queue the request, and if it's the first, process it */
XHRQueue.push([this, arguments]);
if (XHRQueue.length == 1)
this.processQueue();
};
xhr.processQueue = function()
{
var call = XHRQueue[0];
var xhr = call[0];
var args = call[1];
/* you could also set a CSRF token header here */
/* send the request */
_send.apply(xhr, args);
};
xhr.addEventListener('load', function(e)
{
/* you could also retrieve a CSRF token header here */
/* remove the completed request and if there is more, trigger the next */
XHRQueue.shift();
if (XHRQueue.length)
this.processQueue();
});
return xhr;
};
由于最初的问题是关于 ,这里值得一提的是(如此处所述)可以在 a 中使用,但最好避免它,因为异步已被弃用(浏览器可能会发出警告):jQuery.get
async: false
$.get()
XMLHTTPRequest
$.get({
url: url,// mandatory
data: data,
success: success,
dataType: dataType,
async:false // to make it synchronous
});
评论
beforecreate