【问题标题】:Asynchronous programming in javascript (NOT AJAX)javascript中的异步编程(不是AJAX)
【发布时间】:2010-07-20 20:55:40
【问题描述】:

是否可以在 javascript 中异步执行操作(AJAX 除外)?例如,同时迭代多个数组。它是如何完成的?一个简短的例子会很好。由于所有 ajax 污染,搜索它很困难,这不是我想要的。

提前致谢。

【问题讨论】:

  • 听起来您对并行处理感兴趣,不一定是异步执行?我还没有深入研究它,但是 iframe 不使用单独的 js 线程吗?我无法想象它会很有趣,但是您也许可以使用 iframe 中的函数来执行一些并行任务。
  • iframe 可能是一种有趣的技术,尽管我认为 iframe 的开销会比异步编程所带来的额外负面影响更大。
  • 有趣的想法,但我认为在大多数或所有浏览器中,iframe 使用相同的 JS 线程。事实上,我认为除了 Chrome,所有的窗口和标签都使用相同的 JS 线程。

标签: javascript asynchronous


【解决方案1】:

使用web Workers。但请记住,这是一项非常新的功能,并非所有浏览器都得到完全支持。

【讨论】:

  • html 5之前有异步功能吗?
  • @aepheus:并非如此 - JS 是作为单线程创建的,因此虽然您可以使用 Grumdrig 的答案中看到的 setTimeout(),但程序执行仅在一个线程中运行。
【解决方案2】:

你可以使用setTimeout

setTimeout(function () { iterateArray(array1); reportDone(1); }, 0);
setTimeout(function () { iterateArray(array2); reportDone(2); }, 0);

我不确定它的并发性如何,但它是一种异步编程模型。

【讨论】:

  • +1 好的想法,有时只是做一些简单的好事情 :)
  • 我猜这仍然会提供同步执行(尽管正如您所说的那样,它将处于异步模型中)。数组 1 将始终完成,然后数组 2 将开始,等等。除了使代码混乱之外,我看不出有什么原因。
【解决方案3】:

正如 Grumdrig 所说,您可以编写如下代码:

setTimeout(function () { iterateArray(array1); reportDone(1); }, 0);
setTimeout(function () { iterateArray(array2); reportDone(2); }, 0);

但它仍然不会同时运行。以下是调用此类超时后发生的一般情况:

  • setTimeout 调用之后的任何代码都将立即运行,包括返回调用函数。
  • 如果队列中还有其他计时器处于或超过其延迟或间隔时间,它们将一次执行一个。
  • 当任何计时器运行时,另一个计时器可能会达到其间隔/延迟时间,但直到最后一个计时器完成后才会运行。
  • 某些浏览器会优先考虑从用户交互触发的事件,例如 onclickonmousemove,在这种情况下,附加到这些事件的函数将以计时器准确性为代价来执行。
  • 这将一直持续到有一个开口(没有以前调用的计时器或请求执行的事件处理程序)。只有这样,示例代码中的函数才会运行。一次又一次,第一个可能但不一定首先执行。另外,我猜测某些浏览器可能会施加最小延迟时间,这将使任何设置为延迟为 0 毫秒的计时器运行得比预期的还要晚。

显然运行这样的代码没有性能优势。在任何情况下,它都会使事情需要更长的时间才能完成。但是,在单个任务花费的时间过长导致浏览器冻结的情况下(并且可能会触发“脚本花费太长时间”浏览器警告),将其分解为更小更快的执行部分会有所帮助,这些部分会在一段时间后按顺序运行,从而给浏览器一些喘息的时间。

已经提到了Web Workers,如果您不关心IE 兼容性,那么您可以将它们用于真正的并发。然而,出于安全原因,对它们的使用有一些严格的限制。一方面,它们不能以任何方式与 DOM 交互,这意味着对页面的任何更改仍然必须同步完成。此外,传入和传出 worker 的所有数据在传输过程中都被序列化,这意味着不能使用真正的 Javascript 对象。话虽如此,对于密集的数据处理,Web Workers 可能比将一个功能分解为多个计时器延迟任务更好。

【讨论】:

  • 这样做有帮助吗 var tId1 = setTimeout(function () { iterateArray(array1); reportDone(1); }, 0); var tId2= setTimeout(function () { iterateArray(array2); reportDone(2); }, 0);
  • 我看到的唯一区别是将计时器 ID 分配给变量。所有计时器 id 都非常适合取消所述计时器。对于运行一次的 0ms 超时有点毫无意义。
【解决方案4】:

这个领域的一个新发展是HTML5 Web Workers.

【讨论】:

  • 太好了,现在有一种非常令人费解的新方法让我想知道为什么我的处理器在访问网站时会达到峰值! :P
  • @Abel 我也在想同样的事情。现在一个网页可以钉住所有 4 个 cpu 而不是一个。
  • 是的,现在我们可以用空的“for”循环烧掉所有 4 个 CPU!准备好迎接一些热门的笔记本电脑!
【解决方案5】:

JavaScript 通常是单线程的;你不能同时做几件事。如果您的 JavaScript 代码太慢,您将需要卸载工作。正如其他人所指出的,新方法是使用web workers。旧的方法通常是使用 AJAX 并在服务器上完成工作。 (无论是使用 Web Worker 还是使用 AJAX,都必须对数组进行序列化并将结果反序列化)

【讨论】:

    【解决方案6】:

    我不得不同意MooGoo,我也想知道你为什么会一口气跑这么大的阵。

    有一个名为 StratifiedJS 的 JavaScript 扩展,只要它们是异步的,它就允许您一次执行多项操作。此外,webworkers 是一种尴尬的“解决方案”,只会让事情变得更复杂,而且它们不能在 IE 中工作。

    在 StratifiedJS 中你可以写。

    waitfor {
       // do something long lasting here...
    }
    and {
      // do something else at the same time...
    }
    // and when you get here, both are done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-03
      • 2013-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      • 1970-01-01
      相关资源
      最近更新 更多