有没有办法使代码块本身不阻塞
Is there a way to make block of code non-blocking itself
在大量使用node之后,我不得不习惯于以非阻塞方式编写代码,但是我可以做到这一点的主要方法是使用本身异步的函数。例如:stat(f,callback)
或forEach(array, callback)
他们会自动从我认为是主要执行高速公路的地方获取您给他们的任何回调,并在被调用后立即返回。
我想知道的是:我如何告诉 ECMA 引擎异步执行一个函数,不管它是什么?
我的特殊用例涉及在 DOM childList 上迭代一个 for 循环来解析数千个元素;我的问题是每个其他元素都是我想跳过的文本节点。虽然我会使用forEach()
这不是最好的,但我只看到for(a,i=0;a=table[i];i=i+2){/*process 'a'*/}
能够以阻止为代价来纠正它。最好的行动方案是什么?
奖励问题:在JS必须做繁重工作的用例中,NodeJS的编码实践在客户端应用程序中是否站得住脚?
注意:Array.prototype.forEach
是同步的,而不是异步的。 JS标准(ECMAScript 5th edition)中定义的任何内容都不可能是异步的,因为该标准没有定义异步语义(Node.js而DOM定义了
您可以使用setTimeout
(适用于浏览器和 Node.js)或process.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);
指纹:索引=10000指数=20000索引=30000等"完成"
如果有兴趣,请进行更多研究:
setTimeout 和 setInterval 的最小开销时间约为 2 到 10 毫秒,因此,触发数千或数百万个计时器会无缘无故地变慢。 所以基本上,如果你需要在不锁定浏览器的情况下执行数千个或更多的循环,你需要更像一个线程(喘息),并在设定的时间内"刻录"一些代码,而不是设定迭代次数。
- 有没有一种方法可以通过只引用JavaScript来执行代码
- 有没有一个Javascript代码可以看到你的缓存有多满
- 有没有更好的方法来编写这个Show/hide JQuery代码
- 有没有一种方法可以验证asm.js代码
- 有没有一种方法可以制作一个prezi,然后以某种方式将其转换为html和css类型的代码
- 有没有一种方法可以在TestComplete中自动格式化(Javascript)代码
- 有没有一个工具可以将React Elements的javascript代码转换为JSX
- 有没有办法使这段代码更短
- 有没有可能的方法可以在一次ASP按钮单击中同时显示JavaScript和服务器端代码中的消息
- 有没有更短的方法来编写这个 Jquery 代码
- 有没有更简单的方法来编写此代码
- 有没有办法为 RESTful 堆栈生成样板代码
- 有没有办法使代码块本身不阻塞
- 有没有办法减少这段代码
- 有没有办法通过 Greasemonkey 仅在命名帧(而不是所有帧)中运行我的 JS 代码
- 代码只是没有执行,可能有语法问题,或者我可能完全错了
- 有没有一个命令是javascript,允许我重复一行代码一定次数
- JavaScript代码很慢(JQuery).有没有办法优化它
- 有没有办法在 javascript 中的值发生变化时运行代码
- 有没有办法使用 fancybox 在“alt”属性中添加 HTML 代码