NodeJs-promise和async_await語法

Callback hell回調地域

當咱們以同步的方式編寫耗時的代碼,那麼就會阻塞JS的單線程,形成CPU一直等待IO完成纔去執行後面的代碼。javascript

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

異步IO就是爲了解決這個問題的,異步能儘量不讓CPU閒着,它不會在那等着IO完成;而是傳遞給底層的事件循環一個函數,本身去執行下面的代碼。等磁盤IO完成後,函數就會被執行來做爲通知。node

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

功能代碼

實現以下功能:程序員

  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的問題。github

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異步代碼變爲同步的寫法,注意,代碼仍然是異步的promise

語法要求:異步

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

假設擁有了一個promise對象,如今使用async/await能夠這樣寫:async

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站主頁觀看。

相關文章
相關標籤/搜索