我有一个提供标准扩展点的JavaScript小部件。其中之一是beforereate函数。它应该返回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,而不是在回调中返回false。是否有一种方法可以使用jQuery或任何其他浏览器内API执行同步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..
});

因为最初的问题是关于jQuery的。在这里值得一提的是(正如这里提到的),可以在$.get()中使用async: false,但理想情况下要避免它,因为异步XMLHTTPRequest已弃用(浏览器可能会给出警告):

$.get({
  url: url,// mandatory
  data: data,
  success: success,
  dataType: dataType,
  async:false // to make it synchronous
});
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,因为这个警告消息:

从Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27)开始,由于对用户体验的负面影响,主线程上的同步请求已被弃用。

Chrome甚至会在控制台发出警告:

主线程上的同步XMLHttpRequest已弃用,因为它会对最终用户的体验产生不利影响。更多帮助,请访问https://xhr.spec.whatwg.org/。

如果您正在做这样的事情,这可能会破坏您的页面,因为它可能在任何一天停止工作。

如果你想让它看起来仍然是同步的,但仍然不会阻塞,那么你应该使用async/await,可能还应该使用一些基于承诺的ajax,比如新的Fetch API

async function foo() {
  var res = await fetch(url)
  console.log(res.ok)
  var json = await res.json()
  console.log(json)
}

编辑 当用户正在浏览或关闭页面时,chrome正在禁用同步XHR。这包括前卸载,卸载,页面隐藏和可见性改变。

如果这是您的用例,那么您可能需要看看navigator。sendBeacon相反

页面也可以使用http headers或iframe的allow属性禁用sync req

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
    });
}

ES7

在ES7中,你可以使用async 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
    })(); 
}