有没有一种方法可以使代码块不被阻塞?

[英]Is there a way to make block of code non-blocking itself


After using node a lot, I had to get used to writing my code in a non-blocking way, however the main way I can do this is by using functions that are themselves asynchronous. For example: stat(f,callback) or forEach(array, callback) They automatically take whatever callback you gave them out of what I would think to be the main execution highway and return immediately after being called.

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

What I want to know is: how can I tell the ECMA engine to execute a function asynchronously nomatter what it is?

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

My Particular use case involves iterating a for-loop over a DOM childList to parse the thousands of elements; my problem is that every other element is a text node which I'd like to skip over. While I would use forEach() this was not best, I only see for(a,i=0;a=table[i];i=i+2){/*process 'a'*/} being able to rectify that, at the cost of being blocking. What would be the best course of action?

我的特定用例涉及在DOM子列表上迭代for循环以解析数千个元素;我的问题是,所有其他元素都是一个文本节点,我想跳过它。虽然我使用forEach()不是最好的,但我只看到(a, I =0;a=table[I]; I = I +2){/*process 'a'*/}能够纠正这个错误,而代价是阻塞。什么是最好的行动?

Bonus Question: Does NodeJS's coding practices hold any ground in clientside applications in use cases where JS has to do heavy lifting?

额外的问题:在JS必须做大量工作的用例中,NodeJS的编码实践在客户端应用程序中是否有立足之地?

2 个解决方案

#1


3  

Note: Array.prototype.forEach is synchronous, not asynchronous. Anything defined in the JS standard (ECMAScript 5th edition) cannot be asynchronous, because the standard does not define async semantics (Node.js and the DOM do).

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

You can use setTimeout (works in browsers and in Node.js) or process.nextTick (Node.js-specific):

您可以使用setTimeout(在浏览器和Node.js中工作)或进程。nextTick(Node.js-specific):

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

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

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

Be careful when using free variables if you choose to exploit closures, as the variables may be mutated when your callback is finally called.

如果您选择使用闭包,那么在使用自由变量时要小心,因为当您的回调最终被调用时,变量可能会发生突变。

With an async framework, such as Q by kriskowal (portable across Node.js and modern browsers), you can do mapreduce-style programming:

使用异步框架,如kriskowal的Q(可跨节点移植)。),你可以做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.
});

#2


0  

I am in the same boat. I kind of liked Node's async functions, so i wrote this async For and ForEach function. It uses the "setTimeout(Func,0);" trick.

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

Here is the library:

这里是图书馆:

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

Example Usage:

使用示例:

  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"

打印:索引=10000索引=20000索引=30000等“完成”

More research if interested:

更多的研究如果感兴趣:

setTimeout and setInterval have a minimum overhead time of about 2 to 10 milliseconds, therefore, firing thousands or millions of timers is going to be slow for no reason. So basically, if you need to perform thousands or more loops without locking the browser, you need to be more like a thread (gasp), and "burn" some code for a set amount of time, rather than set amount of iterations.

setTimeout和setInterval的开销时间最小为2到10毫秒,因此,毫无理由地,触发数千或数百万个计时器将会很慢。因此,基本上,如果您需要在不锁定浏览器的情况下执行数千个或更多的循环,那么您需要更像一个线程(gasp),并在一定的时间内“烧”一些代码,而不是设置迭代的数量。

智能推荐

注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:http://www.silva-art.net/blog/2012/05/27/54519c1e2e2718f115a981bf76cf1611.html



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告