1

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% 理解异步性。似乎它不仅仅是查看一个函数并找出它是否使用回调。

4

1 回答 1

2

第二个版本不是异步的……嵌套函数只是递归地调用自己(顺便说一句,大数组是个坏主意)。

为了使其异步,您应该例如安排一个计时器(使用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).

于 2013-05-17T21:01:00.457 回答