Nodejs進階系列- 08 使用 Promise/await/async解決 callback hell

由於nodejs的異步特性,我們經常使用callback函數,但是如果在callback裏面又要callback的話,會發現多層嵌套結構非常糟糕,所以被稱爲callback Hell(“回調地獄“),採用Promise來解決這個問題。

const fs = require("fs");
const path = require("path");
const util = require("util");
//例子:判斷目標文件是否是文件夾,如果是則判斷列出目錄內的.txt文佳的大小。

//01-原始寫法,可以看到嵌套非常多層
function withOutPromise() {
    let target = "./abc";
    fs.stat(target, (err, stats) => {
        if (err) {
            throw err
        }
        if (stats.isDirectory()) {
            fs.readdir(target, (err, files) => {
                files.forEach(f => {
                    //console.log(f);
                    if (path.extname(f) === '.txt') {
                        fs.stat(path.join(target, f), (err, stats) => {
                            console.log(f + "大小是 (字節): " + stats.size);
                        })
                    }

                })
            })
        }

    })
};

//withOutPromise();
//a1.txt大小是 (字節): 23
// a2.txt大小是 (字節): 6


//02-使用Promise對含有回調方法的對象進行包裝

let promise=new Promise((resolve,reject)=>{
    fs.readFile('./abc/a1.txt',(err,data)=>{
         //resolve()方法當異步操作成功時調用
         //reject()方法當異步操作失敗是調用;
        if (err){
               reject(err);
           }else{
               resolve(data);
           }

       })
});

//Promise調用可以A 直接調用(不推薦), B、await調用(推薦)

 //A promise的直接調用
 //直接使用promise問題是還是需要使用回調,不建議使用。
   promise.then((data)=>{
      console.log("promise調用成功了!"+data)
  }) .catch((err)=>{
      console.error("promise出異常了:"+err)
  });

 //B 使用await語法調用 ;可以直接得到data,await需要使用async的函數。
async function withPromise() {

    try {
        let data = await promise;
        console.log(data.toString());
    } catch (e) {
        console.log(e)
    }
}

//withPromise();


//03 使用until.promisify() 改寫 上面的 01-原始寫法

 async function withPromiseUtil() {

     try {
         let target = "./abc";
         let pstat = util.promisify(fs.stat);//包裝fs.stat
         let stats = await pstat(target);
         if (stats.isDirectory()) {
             let preaddir = util.promisify(fs.readdir);
             let files = await preaddir(path.join(target))
             //console.log(files)
             for (let f of files) {
                 if (path.extname(f) === '.txt') {
                     let stat = await pstat(path.join(target, f));
                     console.log(f + "大小是 (字節): " + stat.size);

                 }
             }
         }
     } catch (e) {
         console.log(e);
     }


 }

withPromiseUtil();
//a1.txt大小是 (字節): 23
// a2.txt大小是 (字節): 6

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章