在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 回調(diào)
文本編碼
小結(jié)
API 走馬觀花
API 走馬觀花
迭代
小結(jié)
運(yùn)行
回調(diào)
需求
代碼設(shè)計(jì)模式
進(jìn)程介紹
模塊
工程目錄
小結(jié)
小結(jié)
遍歷目錄
小結(jié)
小結(jié)
API 走馬觀花
用途
NPM
小結(jié)
安裝
網(wǎng)絡(luò)操作介紹
二進(jìn)制模塊
什么是 NodeJS
命令行程序
靈機(jī)一點(diǎn)
域(Domain)
應(yīng)用場景
模塊路徑解析規(guī)則
文件拷貝

回調(diào)

NodeJS 最大的賣點(diǎn)——事件機(jī)制和異步 IO,對開發(fā)者并不是透明的。開發(fā)者需要按異步方式編寫代碼才用得上這個(gè)賣點(diǎn),而這一點(diǎn)也遭到了一些 NodeJS 反對者的抨擊。但不管怎樣,異步編程確實(shí)是 NodeJS 最大的特點(diǎn),沒有掌握異步編程就不能說是真正學(xué)會了 NodeJS。本章將介紹與異步編程相關(guān)的各種知識。

在代碼中,異步編程的直接體現(xiàn)就是回調(diào)。異步編程依托于回調(diào)來實(shí)現(xiàn),但不能說使用了回調(diào)后程序就異步化了。我們首先可以看看以下代碼。

function heavyCompute(n, callback) {
    var count = 0,
        i, j;

    for (i = n; i > 0; --i) {
        for (j = n; j > 0; --j) {
            count += 1;
        }
    }

    callback(count);
}

heavyCompute(10000, function (count) {
    console.log(count);
});

console.log('hello');

-- Console ------------------------------
100000000
hello

可以看到,以上代碼中的回調(diào)函數(shù)仍然先于后續(xù)代碼執(zhí)行。JS 本身是單線程運(yùn)行的,不可能在一段代碼還未結(jié)束運(yùn)行時(shí)去運(yùn)行別的代碼,因此也就不存在異步執(zhí)行的概念。

但是,如果某個(gè)函數(shù)做的事情是創(chuàng)建一個(gè)別的線程或進(jìn)程,并與JS主線程并行地做一些事情,并在事情做完后通知 JS 主線程,那情況又不一樣了。我們接著看看以下代碼。

setTimeout(function () {
    console.log('world');
}, 1000);

console.log('hello');

-- Console ------------------------------
hello
world

這次可以看到,回調(diào)函數(shù)后于后續(xù)代碼執(zhí)行了。如同上邊所說,JS 本身是單線程的,無法異步執(zhí)行,因此我們可以認(rèn)為 setTimeout 這類 JS 規(guī)范之外的由運(yùn)行環(huán)境提供的特殊函數(shù)做的事情是創(chuàng)建一個(gè)平行線程后立即返回,讓 JS 主進(jìn)程可以接著執(zhí)行后續(xù)代碼,并在收到平行進(jìn)程的通知后再執(zhí)行回調(diào)函數(shù)。除了 setTimeout、setInterval 這些常見的,這類函數(shù)還包括 NodeJS 提供的諸如 fs.readFile 之類的異步 API。

另外,我們?nèi)匀换氐?JS 是單線程運(yùn)行的這個(gè)事實(shí)上,這決定了 JS 在執(zhí)行完一段代碼之前無法執(zhí)行包括回調(diào)函數(shù)在內(nèi)的別的代碼。也就是說,即使平行線程完成工作了,通知 JS 主線程執(zhí)行回調(diào)函數(shù)了,回調(diào)函數(shù)也要等到 JS 主線程空閑時(shí)才能開始執(zhí)行。以下就是這么一個(gè)例子。

function heavyCompute(n) {
    var count = 0,
        i, j;

    for (i = n; i > 0; --i) {
        for (j = n; j > 0; --j) {
            count += 1;
        }
    }
}

var t = new Date();

setTimeout(function () {
    console.log(new Date() - t);
}, 1000);

heavyCompute(50000);

-- Console ------------------------------
8520

可以看到,本來應(yīng)該在1秒后被調(diào)用的回調(diào)函數(shù)因?yàn)?JS 主線程忙于運(yùn)行其它代碼,實(shí)際執(zhí)行時(shí)間被大幅延遲。