是否有任何原子 javascript 操作来处理 Ajax 的异步性质?

IT技术 javascript ajax asynchronous atomic
2021-02-22 10:14:00

我正在从服务器动态加载代码(函数)并将其作为 javascript 代码执行,然后将其存储在数组中并执行。所有这些代码片段必须只执行一次。伪代码如下

function fetch(foo){
    if (foo in fooArray){
          //Do Nothing
    else{
          //Fetch foo via Ajax and execute foo()
    }
}

问题要复杂得多,但基本上如果我发出以下命令

fetch('someFunctionName');
fetch('someFunctionName');
fetch('someFunctionName');
fetch('someFunctionName');

所有四个都将执行if (foo in fooArray)并假设它不在数组中,并且所有四个将继续获取代码并执行它。我记得在那天学习信号量和互斥量时,javascript 是否有这样的东西。

2个回答

JavaScript 是一种很好的语言,可以很好地处理异步回调、超时、间隔和用户事件,但没有任何并发​​问题。这是可能的,因为 JavaScript 本质上是单线程的——给定的代码片段总是以原子方式执行,永远不会被另一个运行 JavaScript 的线程中断。

您的fetch()功能将始终执行而不会中断。如果它作为 AJAX 回调的一部分执行并且多个 AJAX 回调未决,则它们将排队。

另一个示例:如果您将事件处理程序分配给输入元素,并且您一次触发该事件多次,则事件处理程序将不会同时执行。相反,它们将排队并按顺序执行。这也适用于由setTimeout()/触发的多个事件setInterval()

作为旁注:这是node.js如此健壮的原因之一:它只使用单线程并且从不阻塞 I/O,而是在数据准备好/事件发生时使用回调。

@Tomasz ,如果 AJAX 调用花费的时间太长,也许人们可能不希望有太多(超过 2 或 6 个,取决于浏览器)待处理,所以我在下面提供了一个缓存解决方案..你怎么看?
2021-05-02 10:14:00
Tomasz 我明白你在说什么,thanx。
2021-05-03 10:14:00
严格来说,Web Worker允许并发执行 JS,但由于 Web Worker 和“普通”JS 之间的唯一交互是通过消息发生的,因此您仍然没有任何并发​​问题。
2021-05-04 10:14:00
Javascript 是并发的,但不是并行的。 blog.golang.org/concurrency-is-not-parallelism
2021-05-07 10:14:00
异步的,不是并发的。
2021-05-12 10:14:00

Javascript 本质上是单线程的,因此您不需要互斥锁。您的 fetch 可以设置标志,以便后续的 fetch 调用可以避免进行 ajax 调用,例如:

var beingFetched = {};//map onflight -> callbacks
function fetch(foo){
  if (foo in fooArray){
      //Do Nothing
  } else {
      if (beingFetched.foo) { //note empty array is truthy
          //register a callback
          var callback = function(r){
             //anything you need to do wit the return object r
             //maybe even eval it.
          };
          //the callback would more likely be an argument to fetch itself
          //or you could use a promise API instead so that you can at your will
          //register multiple callbacks - for error, for success etc.
          beingFetched.foo.push(callback); 
      } else {
          beingFetched.foo = [];//truthy
          //Fetch foo via Ajax and execute
          $.ajax("getFoo/"+foo).done(function() {
              _.each(beingFetched.foo, function(cb){
                  cb.apply(cb,arguments);
              });
              delete beingFetched.foo;
          });
      }
  }
}