将同步功能转换为异步

时间:2015-04-18 23:53:32

标签: javascript jquery asynchronous .when

我正在尝试将一系列同步调用变成异步,我正在使用...完成...我对这个东西很新,但是从我在这个主题上所做的所有阅读最近两天,我的代码应该可行。嗯,它确实有效,但并不完全符合我的意思。

在下面的测试代码中,我进行了五次调用,每次调用都需要不同的时间(在我的示例中,它基于字符串的长度...每个字符1/2秒)。我的期望是花费较少时间的调用(即我的示例中的较短长度字符串)将首先完成我快速启动所有五个调用,并且期望结果按照执行时间较短的顺序显示为更长的执行时间。

这是我的代码:

var cars = ["Saab", "Chrysler", "Volvo", "BMW", "GT"];
loopAll(cars);
document.getElementById("demo").innerHTML += "Start!<br>";
function loopAll(array) {
  for (var i in array) {
   $.when( encapsulate(array[i]) ).done( printIt );
  }
  function encapsulate(name){
    var a = $.Deferred();
    setTimeout(function(){pause(name.length*500);a.resolve(name);}, 0);
    return a;
  }
}
function printIt(name){
  document.getElementById("demo").innerHTML += name + "<br>";
}
function pause(ms) {
  ms += new Date().getTime();
  while (new Date() < ms){}
}

阵列中的每个元素都被打印出来,我可以看到它们一个接一个地弹出。但是,它们似乎是同步的,因为它们以数组的原始顺序显示,并且在每个显示的元素之间发生暂停。但是,我的期望是较短的执行功能比较长的执行功能更快完成(和显示)。

注意:我不是要对数组进行排序。我的目的是触发多个调用,让较短的执行完成,而不是顺序完成。我只使用字符串数组作为例子。

3 个答案:

答案 0 :(得分:1)

在这种情况下,超时块并没有真正做任何事情。它会立即执行其功能块。

JavaScript是单线程的,通过使用自制的&#39;暂停&#39;你有效地阻塞线程并导致每个循环同步执行的方法。

如果您有一些同步代码,并且异步备选方案不可用,您可以使用Web worker将它们从主线程中移除。

http://www.html5rocks.com/en/tutorials/workers/basics/

答案 1 :(得分:0)

  

在我下面的测试代码中,我进行了五次调用,每次调用都需要一次   不同的时间(在我的例子中,它是基于长度的   字符串...每个字符1/2秒。)

setTimeout(function(){pause(name.length*500);a.resolve(name);}, 0);

对于创建的每个duration对象,0似乎设置为$.Deferred()?不确定pause的预期结果?

  

我的期望是花费更少时间的电话(即电话号码   我的例子中的长度较短的字符串)将首先完成   快速拨打所有五个电话,并期望显示结果   按照执行时间越短,执行时间越长。

尝试将duration的{​​{1}}设置为setTimeout


&#13;
&#13;
name.length*500
&#13;
var cars = ["Saab", "Chrysler", "Volvo", "BMW", "GT"];
loopAll(cars);
document.getElementById("demo").innerHTML += "Start!<br>";
function loopAll(array) {
  for (var i in array) {
   $.when( encapsulate(array[i]) ).done( printIt );
  }
  function encapsulate(name){
    var a = $.Deferred();
    setTimeout(function(){a.resolve(name);}, name.length*500);
    return a;
  }
}
function printIt(name){
  document.getElementById("demo").innerHTML += name + "<br>";
}

// function pause(ms) {
//  ms += new Date().getTime();
//  while (new Date() < ms){}
// }
&#13;
&#13;
&#13;

答案 2 :(得分:0)

你列出的代码有点像红鲱鱼;事实证明,问题在于声明&#34;我试图将一系列同步调用变为异步。&#34;在大多数JavaScript环境中,这根本不可能。

JS环境通常是单线程的,因此即使您将来使用setTimeout来安排代码执行一段时间,该代码仍将 阻止该线程。有关示例,请参阅this JSFiddlehttp://jsfiddle.net/BinaryMuse/r4ct92c5/

除非您在节点中使用Web Workers(在浏览器中)或external processesfibersnative addons之类的内容,否则您无法异步执行JS代码