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

Javascript / JQuery handling of concurrent / asynchronous calls and data race

本文关键字:数据 竞争 调用 并发 JQuery 处理 Javascript 异步      更新时间:2023-09-26

我目前正在尝试搜索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调用中处理的相同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/侦听事件或运行reflow/repait活动。

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

您也可以使用setTimeout/setInterval来实现异步操作,即使他们不能保证回调将在1000ms或任何延迟后执行,他们只是说它将在最近的可用插槽中执行

  • JavaScript计时器的工作原理
  • JavaScript是否保证是单线程的

尝试使用Promise.race()

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