Javascript 如何让jQuery执行同步而不是异步的Ajax请求?
我有一个JavaScript小部件,它提供标准扩展点。其中之一是Javascript 如何让jQuery执行同步而不是异步的Ajax请求?,javascript,jquery,ajax,asynchronous,Javascript,Jquery,Ajax,Asynchronous,我有一个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),
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);
});
}
但是我想阻止我的小部件创建该项,因此我应该在母函数中返回false
,而不是在回调中。有没有一种方法可以使用jQuery或任何其他浏览器内API执行同步AJAX请求?来自:将异步选项指定为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
});
}
极好的解决方案!我注意到,当我试图实现它时,如果我在success子句中返回一个值,它就会返回为未定义。我必须将其存储在一个变量中并返回该变量。这就是我想出的方法:
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(…)执行Ajax调用代码>
然后再打开一次
jQuery.ajaxSetup({async:true});
我猜它的工作原理与@Adam所建议的相同,但对于那些确实希望将其jQuery.get()
或jQuery.post()
重新配置为更精细的jQuery.ajax()的人来说可能会有所帮助
语法。所有这些答案都忽略了一点,即使用async:false进行Ajax调用将导致浏览器挂起,直到Ajax请求完成。使用流控制库可以在不挂断浏览器的情况下解决此问题。以下是一个示例:
function getURL(url){
return $.ajax({
type: "GET",
url: url,
cache: false,
async: false
}).responseText;
}
//example use
var msg=getURL("message.php");
alert(msg);
例如:
$.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 to 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调用(使用)-如果不能同步执行,jQuery将忽略async
标志
$.ajax({
url: "testserver.php",
dataType: 'jsonp', // jsonp
async: false //IGNORED!!
});
对于JSONP调用,您可以使用:
Ajax调用您自己的域,并在服务器端执行跨域调用
将代码更改为异步工作
使用类似Frame.js的“函数序列器”库(此)
阻止UI而不是阻止执行(这是我最喜欢的方式)
使用async:false
您将获得一个阻塞的浏览器。
对于非阻塞同步解决方案,您可以使用以下方法:
ES6/ECMAScript 2015
在ES6中,您可以使用发电机&
ES7
使用ES7,您只需使用asyc Wait:
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不推荐使用,因为它会对最终用户的体验产生有害影响。如需更多帮助,请查看
这可能会打破你的网页,如果你正在做这样的事情,因为它可能会停止工作的任何一天
如果您希望以一种仍然感觉是同步的但仍然不阻塞的方式来执行,那么您应该使用async/await,可能还应该使用一些基于新API之类承诺的ajax
编辑
当用户导航离开或关闭页面时,chrome正在处理。这包括beforeunload、unload、pagehide和visibilitychange
如果这是您的用例,那么您可能想看一看
页面还可以使用http头或iframe的allow属性禁用sync req首先,我们应该了解何时使用$.ajax以及何时使用$.get/$.post
当我们需要对ajax请求进行低级控制时,比如请求头设置、缓存设置、同步设置等,那么我们应该选择$.ajax
$.get/$.post:当我们不需要对ajax请求进行低级控制时。只需简单地将数据获取/发布到服务器。它是
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
因此,我们不能对$.get/$.post使用其他功能(同步、缓存等)
因此,对于ajax请求的低级别控制(同步、缓存等),我们应该选择$.ajax
$.ajax({
type: 'GET',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
这是我用jQuery实现异步请求的简单方法。我希望这对任何人都有帮助
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();
因为xmlhttprepose
同步操作不受欢迎,所以我提出了以下解决方案来包装XMLHttpRequest
。这允许o
$.ajax({
url: url,
data: data,
success: success,
dataType: dataType
});
$.ajax({
type: 'GET',
url: url,
data: data,
success: success,
dataType: dataType,
async:false
});
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();
/* 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;
};
$.get({
url: url,// mandatory
data: data,
success: success,
dataType: dataType,
async:false // to make it synchronous
});