Javascript/JQuery处理并发/异步调用和数据竞争

Javascript/JQuery处理并发/异步调用和数据竞争,javascript,jquery,ajax,multithreading,asynchronous,Javascript,Jquery,Ajax,Multithreading,Asynchronous,我目前正在尝试搜索Javascript如何处理并行或异步调用中的数据竞争。就我而言,在我的代码中生成异步内容的唯一方法是通过AJAX调用(如果我错了,请更正!),但我认为如果有其他方法,它也会得到同样的处理 因此,作为一个例子,假设我有一个AJAX调用: jQuery.ajax({ //stuff success: function (data) { //do some fancy things with some DOM elements },

我目前正在尝试搜索Javascript如何处理并行或异步调用中的数据竞争。就我而言,在我的代码中生成异步内容的唯一方法是通过AJAX调用(如果我错了,请更正!),但我认为如果有其他方法,它也会得到同样的处理

因此,作为一个例子,假设我有一个AJAX调用:

jQuery.ajax({
    //stuff
    success: function (data) {
        //do some fancy things with some DOM elements
    },
    //possibly more stuff
});
现在假设在该调用之外,我正在运行其他事情,并且我最终使用成功回调在AJAX调用中处理的同一DOM元素执行某些操作(即,在成功回调尝试执行相同操作的同时,在表上追加元素)。换句话说,我的配置以某种数据竞争结束

Javascript如何处理这个问题?当我的AJAX响应返回时,是否会抢占当前正在运行的函数,以便执行AJAX调用?有什么东西可以保证我对DOM元素(或javascript变量)所做的是某种原子操作吗?所以,如果我需要运行一个必须是原子的函数,我怎么能告诉解释器呢


另外,Javascript上是否有一些屏蔽来防止死锁?比方说,如果我运行两个并行的AJAX调用,并且每个调用都取决于另一个调用的完成。

JavaScript没有任何针对这种情况的内置保护。作为代码设计的一部分,您需要确保不会出现不知道两个冲突函数中的哪一个将首先执行的情况


这需要一些计划。您可以将一个Ajax调用放在另一个Ajax调用的回调中,或者使用事件和属性让其他函数知道某些内容是否已准备好进行处理,或者是否正在使用某个对象,因此不应触碰它,等等。

对于第一个问题:

现在假设在该调用之外,我正在运行其他事情,并且我最终使用成功回调在AJAX调用中处理的同一DOM元素执行某些操作(即,在成功回调尝试执行相同操作的同时,在表上追加元素)。换句话说,我的配置以某种数据竞争结束

为此,您可以简单地使用jQuery的
$.Deferred
功能。所有的
$.ajax
调用返回jquery调用的延迟对象。也称为承诺对象。在其他语言中也被称为未来。这允许您在请求完成后执行功能

var req = $.get(url, successFunc);
req.done(someOtherFunc);
关于第二个问题:

比方说,如果我运行两个并行AJAX调用,并且每个调用都取决于另一个调用的完成

我认为您在这里寻找的是$.when,它允许您仅在请求列表已解决时运行功能

$.when([req1, req2, req3], function (res1, res2, res3) {});

浏览器-扩展javascript(打开页面的地方)就像一个单线程应用程序一样运行,一次只能做一件事

这意味着在任何时间点,浏览器都可以运行javascript/侦听事件或运行回流/重新编写活动

由于在任何时间点都是这种情况,浏览器窗口只能执行1个函数,这意味着当ajax响应返回时,如果有函数正在运行,则ajax回调将添加到执行队列中,该队列将在当前函数完成时执行

您还可以通过使用setTimeout/setInterval实现异步操作,即使它们不能保证回调将在1000毫秒后执行,或者不管给定什么延迟,它们只是说它将在最近的可用插槽中执行

尝试利用


如果某些内容取决于异步操作的结果,那么所有内容都必须变为异步,使用嵌套回调或使用承诺。您可能会发现这一点很有用。这更好地回答了关于死锁的问题,但是,如果Javascript似乎无法处理原子功能,我如何保证给定的AJAX调用不会触及使用属性的对象?例如,这将是对对象的原子访问:var=0;函数(obj){a=1;//access obj a=0;}但这显然不是真的,因为对a=0和a=1的调用不是原子的。我不是100%确定我理解了,但我想你的问题的答案是JavaScript不是原子的。如果某些操作失败,则没有内置的方法来撤消部分调用。您必须使用try-catch等来完成此操作。现在我看到我弄乱了“原子访问函数”,因为它不检查“var”的状态。无论如何,有人发布了一个链接,描述我的成功函数将被推送到事件队列中,因此它将在所有事件完成后运行。因此,我认为不可能有直接的数据竞争。对。只要您在回调中,这就是唯一正在运行的javascript。只有一根线。异步操作完成后,会将回调添加到堆栈中。因此,如果您必须同时运行异步调用,您将不知道哪个回调将首先进入堆栈,但一次只能运行一个。我明白了,这很酷。但是,如果想要在我的表中添加内容,我必须等待AJAX调用返回,以避免数据竞争?我不明白如果一种语言不能处理数据竞争而不使事情稍微同步,为什么它会实现异步调用。事实上,我看不出执行
req.done(someOtherFunc)之间的区别var request = function(url) {
  return new Promise(function(resolve, reject) {
    var res = $.ajax({
        url: url,
        type: "GET"
    });
    res.then(function success(data) {
      resolve(data)
    }, function error(jqxhr, textStatus, errorThrown) {
      reject([textStatus, errorThrown])
    })
  })  
};

var promises = Promise.race([
  request("https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js")
, request("https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js")
]);

promises.then(function(response) {
 console.log(response)
}, function(error) {
  console.log(error)
});