亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

NodeJS同步和異步實(shí)例代碼講述異步編程

 更新時間:2024年01月01日 09:58:02   投稿:yin  
異步編程是NodeJS最大的特點(diǎn),異步編程依托于回調(diào)來實(shí)現(xiàn),有很多特有的代碼設(shè)計模式,為了實(shí)現(xiàn)同樣的功能,使用同步方式和異步方式編寫的代碼會有很大差異,本文通過幾個同步和異步實(shí)例代碼講述異步編程的使用方法

NodeJS最大的賣點(diǎn)——事件機(jī)制和異步IO。開發(fā)者需要按異步方式編寫代碼才用得上這個賣點(diǎn)。但不管怎樣,異步編程確實(shí)是NodeJS最大的特點(diǎn),沒有掌握異步編程就不能說是真正學(xué)會了NodeJS。

異步編程的直接體現(xiàn)就是回調(diào)。異步編程依托于回調(diào)來實(shí)現(xiàn),但不能說使用了回調(diào)后程序就異步化了。異步編程有很多特有的代碼設(shè)計模式,為了實(shí)現(xiàn)同樣的功能,使用同步方式和異步方式編寫的代碼會有很大差異。,本文通過幾個同步和異步實(shí)例代碼講述異步編程的使用方法。

函數(shù)返回值

使用一個函數(shù)的輸出作為另一個函數(shù)的輸入是很常見的需求,在同步方式下一般按以下方式編寫代碼:

var output = fn1(fn2('input'));
// Do something.

而在異步方式下,由于函數(shù)執(zhí)行結(jié)果不是通過返回值,而是通過回調(diào)函數(shù)傳遞,因此一般按以下方式編寫代碼:

fn2('input', function (output2) {
    fn1(output2, function (output1) {
        // Do something.
    });
});

可以看到,這種方式就是一個回調(diào)函數(shù)套一個回調(diào)函多,套得太多了很容易寫出>形狀的代碼。

遍歷數(shù)組

在遍歷數(shù)組時,使用某個函數(shù)依次對數(shù)據(jù)成員做一些處理也是常見的需求。如果函數(shù)是同步執(zhí)行的,一般就會寫出以下代碼:

var len = arr.length,
    i = 0;

for (; i < len; ++i) {
    arr[i] = sync(arr[i]);
}

// All array items have processed.

如果函數(shù)是異步執(zhí)行的,以上代碼就無法保證循環(huán)結(jié)束后所有數(shù)組成員都處理完畢了。如果數(shù)組成員必須一個接一個串行處理,則一般按照以下方式編寫異步代碼:

(function next(i, len, callback) {
    if (i < len) {
        async(arr[i], function (value) {
            arr[i] = value;
            next(i + 1, len, callback);
        });
    } else {
        callback();
    }
}(0, arr.length, function () {
    // All array items have processed.
}));

可以看到,以上代碼在異步函數(shù)執(zhí)行一次并返回執(zhí)行結(jié)果后才傳入下一個數(shù)組成員并開始下一輪執(zhí)行,直到所有數(shù)組成員處理完畢后,通過回調(diào)的方式觸發(fā)后續(xù)代碼的執(zhí)行。

如果數(shù)組成員可以并行處理,但后續(xù)代碼仍然需要所有數(shù)組成員處理完畢后才能執(zhí)行的話,則異步代碼會調(diào)整成以下形式:

(function (i, len, count, callback) {
    for (; i < len; ++i) {
        (function (i) {
            async(arr[i], function (value) {
                arr[i] = value;
                if (++count === len) {
                    callback();
                }
            });
        }(i));
    }
}(0, arr.length, 0, function () {
    // All array items have processed.
}));

可以看到,與異步串行遍歷的版本相比,以上代碼并行處理所有數(shù)組成員,并通過計數(shù)器變量來判斷什么時候所有數(shù)組成員都處理完畢了。

異常處理

JS自身提供的異常捕獲和處理機(jī)制——try..catch..,只能用于同步執(zhí)行的代碼。以下是一個例子。

function sync(fn) {
    return fn();
}

try {
    sync(null);
    // Do something.
} catch (err) {
    console.log('Error: %s', err.message);
}

-- Console ------------------------------
Error: object is not a function

可以看到,異常會沿著代碼執(zhí)行路徑一直冒泡,直到遇到第一個try語句時被捕獲住。但由于異步函數(shù)會打斷代碼執(zhí)行路徑,異步函數(shù)執(zhí)行過程中以及執(zhí)行之后產(chǎn)生的異常冒泡到執(zhí)行路徑被打斷的位置時,如果一直沒有遇到try語句,就作為一個全局異常拋出。以下是一個例子。

function async(fn, callback) {
    // Code execution path breaks here.
    setTimeout(function () {
        callback(fn());
    }, 0);
}

try {
    async(null, function (data) {
        // Do something.
    });
} catch (err) {
    console.log('Error: %s', err.message);
}

-- Console ------------------------------
/home/user/test.js:4
        callback(fn());
                 ^
TypeError: object is not a function
    at null._onTimeout (/home/user/test.js:4:13)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

因?yàn)榇a執(zhí)行路徑被打斷了,我們就需要在異常冒泡到斷點(diǎn)之前用try語句把異常捕獲住,并通過回調(diào)函數(shù)傳遞被捕獲的異常。于是我們可以像下邊這樣改造上邊的例子。

function async(fn, callback) {
    // Code execution path breaks here.
    setTimeout(function () {
        try {
            callback(null, fn());
        } catch (err) {
            callback(err);
        }
    }, 0);
}

async(null, function (err, data) {
    if (err) {
        console.log('Error: %s', err.message);
    } else {
        // Do something.
    }
});

-- Console ------------------------------
Error: object is not a function

可以看到,異常再次被捕獲住了。在NodeJS中,幾乎所有異步API都按照以上方式設(shè)計,回調(diào)函數(shù)中第一個參數(shù)都是err。因此我們在編寫自己的異步函數(shù)時,也可以按照這種方式來處理異常,與NodeJS的設(shè)計風(fēng)格保持一致。

有了異常處理方式后,我們接著可以想一想一般我們是怎么寫代碼的?;旧希覀兊拇a都是做一些事情,然后調(diào)用一個函數(shù),然后再做一些事情,然后再調(diào)用一個函數(shù),如此循環(huán)。如果我們寫的是同步代碼,只需要在代碼入口點(diǎn)寫一個try語句就能捕獲所有冒泡上來的異常,示例如下。

function main() {
    // Do something.
    syncA();
    // Do something.
    syncB();
    // Do something.
    syncC();
}

try {
    main();
} catch (err) {
    // Deal with exception.
}

但是,如果我們寫的是異步代碼,就只有呵呵了。由于每次異步函數(shù)調(diào)用都會打斷代碼執(zhí)行路徑,只能通過回調(diào)函數(shù)來傳遞異常,于是我們就需要在每個回調(diào)函數(shù)里判斷是否有異常發(fā)生,于是只用三次異步函數(shù)調(diào)用,就會產(chǎn)生下邊這種代碼。

function main(callback) {
    // Do something.
    asyncA(function (err, data) {
        if (err) {
            callback(err);
        } else {
            // Do something
            asyncB(function (err, data) {
                if (err) {
                    callback(err);
                } else {
                    // Do something
                    asyncC(function (err, data) {
                        if (err) {
                            callback(err);
                        } else {
                            // Do something
                            callback(null);
                        }
                    });
                }
            });
        }
    });
}

main(function (err) {
    if (err) {
        // Deal with exception.
    }
});

可以看到,回調(diào)函數(shù)已經(jīng)讓代碼變得復(fù)雜了,而異步方式下對異常的處理更加劇了代碼的復(fù)雜度。如果NodeJS的最大賣點(diǎn)最后變成這個樣子,那就沒人愿意用NodeJS了。

總結(jié)

不掌握異步編程就不算學(xué)會NodeJS。異步編程下的函數(shù)間數(shù)據(jù)傳遞、數(shù)組遍歷和異常處理與同步編程有很大差別。

到此這篇關(guān)于NodeJS同步和異步實(shí)例代碼講述異步編程的文章就介紹到這了,更多相關(guān)NodeJS異步編程的使用實(shí)例內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Nodejs極簡入門教程(一):模塊機(jī)制

    Nodejs極簡入門教程(一):模塊機(jī)制

    這篇文章主要介紹了Nodejs極簡入門教程(一):模塊機(jī)制,本文講解了模塊基礎(chǔ)知識、模塊的加載、包等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • Node.js Stream ondata觸發(fā)時機(jī)與順序的探索

    Node.js Stream ondata觸發(fā)時機(jī)與順序的探索

    今天小編就為大家分享一篇關(guān)于Node.js Stream ondata觸發(fā)時機(jī)與順序的探索,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • nodejs body-parser 解析post數(shù)據(jù)實(shí)例

    nodejs body-parser 解析post數(shù)據(jù)實(shí)例

    下面小編就為大家?guī)硪黄猲odejs body-parser 解析post數(shù)據(jù)實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • nodejs操作mongodb的增刪改查功能實(shí)例

    nodejs操作mongodb的增刪改查功能實(shí)例

    這篇文章主要介紹了nodejs操作mongodb的增刪改查功能,簡單分析了mongodb模塊的安裝并結(jié)合實(shí)例形式分析了nodejs操作mongodb數(shù)據(jù)庫進(jìn)行增刪改查的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-11-11
  • Node.js的文件權(quán)限及讀寫flag詳解

    Node.js的文件權(quán)限及讀寫flag詳解

    Node.js對文件的讀寫還是相當(dāng)靈活的,因?yàn)樽约豪鲜怯洸蛔∥募蚰夸洐?quán)限的數(shù)值表達(dá)和字符表達(dá)。所以整理出這篇文章,方便以后查閱,下面來一起看看吧。
    2016-10-10
  • node.js 中間件express-session使用詳解

    node.js 中間件express-session使用詳解

    這篇文章主要給大家介紹了node.js中間件express-session使用的相關(guān)資料,文中介紹的非常詳細(xì),對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起看看吧。
    2017-05-05
  • puppeteer實(shí)現(xiàn)html截圖的示例代碼

    puppeteer實(shí)現(xiàn)html截圖的示例代碼

    通過Puppeteer的提供的api直接控制Chrome模擬大部分用戶操作來進(jìn)行UI Test或者作為爬蟲訪問頁面來收集數(shù)據(jù),這篇文章主要介紹了puppeteer實(shí)現(xiàn)截圖的示例代碼,感興趣的可以了解一下
    2019-01-01
  • 如何構(gòu)建一個?NodeJS?影院微服務(wù)并使用?Docker?部署

    如何構(gòu)建一個?NodeJS?影院微服務(wù)并使用?Docker?部署

    微服務(wù)是一個單獨(dú)的自包含單元,與其他許多單元一起構(gòu)成一個大型應(yīng)用程序,這篇文章主要介紹了如何構(gòu)建一個NodeJS影院微服務(wù)并使用Docker部署,在這個系列中,將構(gòu)建一個 NodeJS 微服務(wù),并使用 Docker Swarm 集群進(jìn)行部署,需要的朋友可以參考下
    2023-08-08
  • Node.js中代碼重復(fù)與不一致的問題及解決方案

    Node.js中代碼重復(fù)與不一致的問題及解決方案

    在 Node.js 開發(fā)中,代碼重復(fù)和不一致是常見的問題,尤其是在項(xiàng)目規(guī)模擴(kuò)大和團(tuán)隊協(xié)作時,這些問題不僅會增加維護(hù)成本,還可能導(dǎo)致邏輯錯誤和性能問題,本文將探討這些問題的常見原因,并提供相應(yīng)的解決方案,需要的朋友可以參考下
    2025-03-03
  • nodejs實(shí)現(xiàn)套接字服務(wù)功能詳解

    nodejs實(shí)現(xiàn)套接字服務(wù)功能詳解

    這篇文章主要介紹了nodejs實(shí)現(xiàn)套接字服務(wù)功能,簡單描述了套接字的概念、功能,并結(jié)合實(shí)例形式分析了nodejs使用socket對象創(chuàng)建及使用套接字進(jìn)行數(shù)據(jù)傳輸相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2018-06-06

最新評論