NodeJs-promise和async_await語法


Callback hell回調地域

當我們以同步的方式編寫耗時的代碼,那么就會阻塞JS的單線程,造成CPU一直等待IO完成才去執行后面的代碼。

而CPU的執行速度是遠遠大於硬盤IO速度的,這樣等待只會造成資源的浪費。

異步IO就是為了解決這個問題的,異步能盡可能不讓CPU閑着,它不會在那等着IO完成;而是傳遞給底層的事件循環一個函數,自己去執行下面的代碼。等磁盤IO完成后,函數就會被執行來作為通知。

雖然異步回調的編程方式能充分利用CPU,但是當代碼邏輯變的越來越復雜后,新的問題出現了——Callback hell回調地域!

功能代碼

實現如下功能:

  1. 判斷一個文件是文件還是目錄;
  2. 如果是目錄,讀取這個目錄下的文件,找出結尾是txt的文件;
  3. 獲取這些txt文件大小。

異步方式

function withoutPromise() {
    let target = "test";
    fs.stat(target, (err, stat)=>{
        if(err){
            throw err;
        }
        // 如果是文件夾
        if(stat.isDirectory()){
            fs.readdir(target, (err, files)=>{
                // 遍歷files
                files.forEach( f =>{
                    if(path.extname(f) === '.txt'){
                        fs.stat(path.join(target, f), (err, stat)=>{
                            console.log(f+ " : "+stat.size);
                        });
                    }
                } );
            });
        }
    });
}

Promise方式

async function withPromise() {
    let target = "test";
    //將fs.stat轉為一個可以返回Promise對象的方法
    let pstat = util.promisify(fs.stat);
    let stat = await pstat(target);
    // 如果是文件夾
    if(stat.isDirectory()){
        //將fs.readdir轉為一個可以返回Promise對象的方法
        let preaddir = util.promisify(fs.readdir)
        let files = await preaddir(target)
        files.forEach( async (f) => {
            if(path.extname(f) === '.txt'){
                let stat = await pstat(path.join(target, f));
                console.log(stat.size);
            }
        });
    }
}

Promise和async/await

Promiseasync/await便是為了解決Callback hell的問題。

promise

promise的作用是對異步回調代碼包裝一下,把原來的一個回調函數拆成2個回調函數,這樣的好處是可讀性更好。語法如下:

// 創建promise對象
let promise = new Promise((resolve, reject)=>{
    // 在異步操作成功的情況選調用resolve,失敗的時候調用reject
    fs.readFile('xxx.txt',(err, data)=>{
        if(err){
            reject(err)
        }else {
            resolve(data.toString())
        }
    })
});
// 使用promise
promise.then((text)=>{
    //then方法是當Promise內部調用了resolve的時候執行
}).catch((err)=>{
    //catch方法是當Promise內部調用了reject的時候執行
    console.log(err);
})
  • 語法注意:Promise內部的resolve和reject方法只能調用一次,調用了這個就不能再調用了那個;如果調用,則無效。

async/await

async/await的作用是直接將Promise異步代碼變為同步的寫法,注意,代碼仍然是異步的

語法要求:

  • await只能用在async修飾的方法中,但是有async不要求一定有await
  • await后面只能跟async方法和promise

假設擁有了一個promise對象,現在使用async/await可以這樣寫:

async function asyncDemo() {
    try {
        // 當promise的then方法執行的時候
        let text = await promise
        // 當你用promise包裝了所有的異步回調代碼后,就可以一直await,真正意義實現了以同步的方式寫異步代碼
        console.log('異步道明執行');
    }catch (e){
        // 捕獲到promise的catch方法的異常
        console.log(e);
    }
}
asyncDemo()
console.log('我是同步代碼');

異步代碼的終極寫法

  1. 先使用promise包裝異步回調代碼,可使用node提供的util.promisify方法;
  2. 使用async/await編寫異步代碼。

參考

  • 黑馬程序員 120天全棧區塊鏈開發 開源教程

    https://github.com/itheima1/BlockChain

學習視頻

一番同步了對應的學習視頻到B站,長按識別可訪問一番B站主頁觀看。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM