用Promise建構函式來解決地獄回撥問題

EsunR醬發表於2018-12-02

簡介

  1. Promise 是一個 建構函式,既然是建構函式, 那麼,我們就可以 new Promise() 得到一個 Promise 的例項;
  2. 在 Promise 上,有兩個函式,分別叫做 resolve(成功之後的回撥函式) 和 reject(失敗之後的回撥函式)
  3. 在 Promise 建構函式的 Prototype 屬性上,有一個 .then() 方法,也就說,只要是 Promise 建構函式建立的例項,都可以訪問到 .then() 方法
  4. Promise 表示一個 非同步操作;每當我們 new 一個 Promise 的例項,這個例項,就表示一個具體的非同步操作;
  5. 既然 Promise 建立的例項,是一個非同步操作,那麼,這個 非同步操作的結果,只能有兩種狀態:
  • 狀態1: 非同步執行成功了,需要在內部呼叫 成功的回撥函式 resolve 把結果返回給呼叫者;
  • 狀態2: 非同步執行失敗了,需要在內部呼叫 失敗的回撥函式 reject 把結果返回給呼叫者;
  • 由於 Promise 的例項,是一個非同步操作,所以,內部拿到 操作的結果後,無法使用 return 把操作的結果返回給呼叫者; 這時候,只能使用回撥函式的形式,來把 成功 或 失敗的結果,返回給呼叫者;
  1. 我們可以在 new 出來的 Promise 例項上,呼叫 .then() 方法,【預先】 為 這個 Promise 非同步操作,指定 成功(resolve) 和 失敗(reject) 回撥函式;

舉個例子

const fs = require('fs')

function getFileByPaht(fpath) {
  var promise = new Promise(function (resolve, reject) {
    fs.readFile(fpath, 'utf-8', (err, dataStr) => {
      if (err) return reject(err);
      resolve(dataStr);
    });
  });
  return promise;
}

getFileByPaht('./files/3.txt')
.then(function (dataStr) {
  console.log(dataStr);
}, function (err) {
  console.log(err.message);
})

複製程式碼

Promise的內部執行順序

avatar

用Promise的 .then() 方法解決地獄回撥

注意: Promise的 reject 部分傳入的函式可以為空,即可不寫檔案讀取失敗後的操作,

getFileByPath('./files/1222.txt')
  .then(function (data) {
    console.log(data);
    return getFileByPath('./files/2.txt');
  }, 
  .then(function (data) {
    console.log(data);
    return getFileByPath('./files/3.txt');
  })
  .then(function (data) {
    console.log(data);
  })
複製程式碼

Promise中的異常處理

情況一:在讀取檔案出錯的部分報錯,但不影響後方程式碼的執行

getFileByPath('./files/1222.txt')
  .then(function (data) {
    console.log(data);
    return getFileByPath('./files/2.txt');
  }, function (err) {
    console.log('讀取失敗:' + err.message);
    return getFileByPath('./files/2.txt');
  })
  .then(function (data) {
    console.log(data);
    return getFileByPath('./files/3.txt');
  })
  .then(function (data) {
    console.log(data);
  })
複製程式碼

情況二:如果前面任何的Promise執行失敗,就停止執行後面的方法(catch捕獲機制)

getFileByPath('./files/1222.txt')
  .then(function (data) {
    console.log(data);
    return getFileByPath('./files/2.txt');
  })
  .then(function (data) {
    console.log(data);
    return getFileByPath('./files/3.txt');
  })
  .then(function (data) {
    console.log(data);
  })
  .catch(function (err) {  
    console.log('異常捕獲: ' + err.message);
  })
複製程式碼

相關文章