English 中文(简体)
有没有办法让代码块本身不阻塞
原标题:Is there a way to make block of code non-blocking itself

在大量使用node之后,我不得不习惯以非阻塞的方式编写代码,但我能做到这一点的主要方法是使用本身异步的函数。例如:stat(f,callback)forEach(array,callback)它们会自动从我认为的主要执行高速公路中提取你给它们的任何回调,并在被调用后立即返回。

我想知道的是:我如何告诉ECMA引擎异步执行一个函数,不管它是什么

我的特定用例涉及在DOM子列表上迭代for循环来解析数千个元素;我的问题是,其他每个元素都是一个文本节点,我想跳过它。虽然我会为Each()使用,但这不是最好的,我只看到(a,I=0;a=table[I];I=I+2){/*进程a*/}

附加问题:在JS必须承担繁重工作的用例中,NodeJS的编码实践在客户端应用程序中是否占有一席之地?

最佳回答

注意:Array.prototype.forEach是同步的,不是异步的。JS标准中定义的任何内容(ECMAScript第5版)不能是异步的,因为该标准没有定义异步语义(Node.js和DOM都定义了)。

您可以使用setTimeout(适用于浏览器和Node.js)或进程.nextTick(特定于Node.js):

for (...) {
    doWorkAsync(...);
}

function doWorkAsync(...) {
    setTimeout(doWorkSync.bind(null, ...), 0);
}

function doWorkSync(...) {
    ...
}

如果你选择利用闭包,在使用自由变量时要小心,因为当你的回调函数最终被调用时,变量可能会发生变异。

使用异步框架,例如Q by kriskowal(可跨Node.js和现代浏览器移植),您可以进行mapreduce风格的编程:

var Q = require( q );  // npm package  q 

function getWorkloads() {
    var workloads = [ ];
    for (...) {
        workloads.push(Q.fcall(doWorkSync.bind(null, ...)));
    }
    return workloads;
}

Q.all(getWorkloads()).then(function (results) {
    // results array corresponds to
    // the array returned by getWorkloads.
});
问题回答

我在同一条船上。我有点喜欢Node的异步函数,所以我写了这个异步For和ForEach函数。它使用“setTimeout(Func,0);”技巧。

这里是图书馆:

  var WilkesAsyncBurn = function()
  {
    var Now = function() {return (new Date());};
    var CreateFutureDate = function(milliseconds)
    {
      var t = Now();
      t.setTime(t.getTime() + milliseconds);
      return t;
    };
    var For = function(start, end, eachCallback, finalCallback, msBurnTime)
    {
      var i = start;
      var Each = function()
      {
        if(i==-1) {return;} //always does one last each with nothing to do
        setTimeout(Each,0);
        var burnTimeout = CreateFutureDate(msBurnTime);
        while(Now() < burnTimeout)
        {
          if(i>=end) {i=-1; finalCallback(); return;}
          eachCallback(i);
          i++;
        }
      };
      Each();
    };
    var ForEach = function(array, eachCallback, finalCallback, msBurnTime)
    {
      var i = 0;
      var len = array.length;
      var Each = function()
      {
        if(i==-1) {return;}
        setTimeout(Each,0);
        var burnTimeout = CreateFutureDate(msBurnTime);
        while(Now() < burnTimeout)
        {
          if(i>=len) {i=-1; finalCallback(array); return;}
          eachCallback(i, array[i]);
          i++;
        }
      };
      Each();
    };

    var pub = {};
    pub.For = For;          //eachCallback(index); finalCallback();
    pub.ForEach = ForEach;  //eachCallback(index,value); finalCallback(array);
    WilkesAsyncBurn = pub;
  };

示例用法:

  WilkesAsyncBurn(); // Init the library
  console.log("start");
  var FuncEach = function(index)
  {
    if(index%10000==0)
    {
        console.log("index=" + index);
    }
  };
  var FuncFinal = function()
  {
    console.log("done"); 
  };
  WilkesAsyncBurn.For(0,2000000,FuncEach,FuncFinal,50);

prints: index=10000 index=20000 index=30000 etc "done"

如有兴趣,请进行更多研究:

setTimeout和setInterval的最小开销时间约为2到10毫秒,因此,无缘无故地启动数千或数百万个计时器会很慢。所以基本上,如果你需要在不锁定浏览器的情况下执行数千个或更多的循环,你需要更像一个线程(喘息),并在设定的时间内“燃烧”一些代码,而不是设定迭代次数。





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.