JavaScript 的突出特性之一(或不利特性,取决于您对该主题的看法)是它的异步特性。我理解代码流是如何工作的,但我不是 100% 了解是什么让异步代码“异步”。
当然,联系服务器或读取/写入数据库是一个异步操作。但是通常非异步处理的东西呢?我可以编写使用回调使其全天异步的代码。
同步示例
var arrayToIterate = [1,2,3,4,5,6,7,8,9, ... ]
//Say this array length is in the hundreds of millions.
var addArrayContents = function(array) {
var total = 0;
for (var i = 0, len = array.length; i <= len; i++) {
total = total + array[i];
}
return total;
};
var arrayTotal = addArrayContents(arrayToIterate);
异步示例
var arrayToIterate = [1,2,3,4,5,6,7,8,9, ... ]
//Say this array length is in the hundreds of millions.
var addArrayContents = function(array, callback) {
var iterator = function(total, arIndex, cb) {
if (arIndex == array.length) {
return cb(total);
}
total = total + array[arIndex];
arIndex++;
iterator(total, arIndex, cb)
};
iterator(0, 0, callback);
};
addArrayContents(arrayToIterate, function(result){
console.log(result);
// Do stuff
});
如您所知,这两个函数做同样的事情,一个是异步的,一个不是。是否有经验法则来决定异步执行某些操作的最佳时间而不是同步执行?在上面的示例中,同步函数在将这些数字加在一起时会出现问题,而异步版本在运行时不会挂起。
我只是觉得我不是 100% 理解异步。它似乎不仅仅是查看一个函数并确定它是否使用回调。
最佳答案
第二个版本不是异步的...嵌套函数只是递归地调用自身(顺便说一句,大数组是个坏主意)。
要使其异步,您应该安排一个计时器(使用 setTimeout
),以便稍后继续计算。
var index = 0;
var total = 0;
function step() {
if (index < array.length) {
total += array[index++];
setTimeout(step, 0);
} else {
callback(total);
}
}
setTimeout(step, 0);
在这种情况下,函数将立即返回给调用者,一旦计算完成,完成回调将稍后(异步)调用。
例如,在内部实现 setTimeout
的一种方法是保留一堆等待触发的计时器事件。当 JS 环境完成当前事件时,它将检查接下来要生成什么,然后调用处理程序从堆中删除该项目。
还请注意,除了计时器事件之外,还有鼠标事件、网络事件、消息事件等等...通常,计时器事件的优先级最低,因此只有在没有其他事情可做时才会调用代码(这也是为什么计时不准确,指定的延迟只是最小延迟)。
即使没有其他事件,例如浏览器中的 JS 通常会在调用计时器处理程序之前先执行 DOM 重绘(这就是为什么即使在使用 setTimeout 执行处理时进度条也会更新的原因) (f, 0)
。
关于javascript - 什么构成了异步 JavaScript?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16617679/