Promise的使用

LTT1995發表於2020-11-15
 /*
  什麼時候適合用 Promise 而不是傳統回撥函式?
  當需要多次順序執行非同步操作的時候,例如,如果想通過非同步方法先後檢測使用者名稱和密碼,
  需要先非同步檢測使用者名稱,然後再非同步檢測密碼的情況下就很適合 Promise。
  */
/*Promise 是一個 ECMAScript 6 提供的類,
  目的是更加優雅地書寫複雜的非同步任務。*/
//函式瀑布
//   setTimeout(function () {
//     console.log("First");
//     setTimeout(function () {
//       console.log("Second");
//       setTimeout(function () {
//         console.log("Third");
//       }, 1000);
//     }, 2000);
//   }, 1000);
//使用promise來改進
new Promise(function (resolve, reject) {
  setTimeout(function () {
    console.log("First");
    resolve();
  }, 1000);
})
  .then(function () {
    return new Promise(function (resolve, reject) {
      setTimeout(function () {
        console.log("Second");
        resolve();
      }, 2000);
    });
  })
  .then(function () {
    setTimeout(function () {
      console.log("Third");
    }, 1000);
  });
//當Promise被構造時,起始函式會被非同步執行
new Promise(function (resolve, reject) {
  console.log("Run");
}); //Run
//resolve和reject都是函式,其中resolve代表一切正常
//reject是出現異常時所呼叫的
new Promise(function (resolve, reject) {
  var a = 0;
  var b = 1;
  if (b == 0) reject("Diveide zero");
  else resolve(a / b);
})
  .then(function (value) {
    //引數value是resolve的結果
    console.log("a / b =" + value);
  })
  .catch(function (err) {
    //引數err是reject的結果
    console.log(err);
  })
  .finally(function () {
    console.log("End");
  }); //結束
/*Promise 類有 .then() .catch() 和 .finally() 三個方法,
  這三個方法的引數都是一個函式,
  .then() 可以將引數中的函式新增到當前 Promise 的正常執行序列,
  .catch() 則是設定 Promise 的異常處理序列,.finally() 是在 Promise 執行的最後一定會執行的序列。
   .then() 傳入的函式會按順序依次執行,有任何異常都會直接跳到 catch 序列:
   */
new Promise(function (resolve, reject) {
  console.log(1111);
  resolve(2222);
})
  .then(function (value) {
    console.log(value);
    return 3333;
  })
  .then(function (value) {
    console.log(value);
    throw "An error"; // then 塊預設會向下順序執行,return 是不能中斷的,可以通過 throw 來跳轉至 catch 實現中斷。
  })
  .catch(function (err) {
    console.log(err);
  }); //結果依次是1111 2222 3333 An error
/*
  resolve() 中可以放置一個引數用於向下一個 then 傳遞一個值,
  then 中的函式也可以返回一個值傳遞給 then。但是,
  如果 then 中返回的是一個 Promise 物件,那麼下一個 then 將相當於對這個返回的 Promise 進行操作,
  這一點從剛才的計時器的例子中可以看出來。
  reject() 引數中一般會傳遞一個異常給之後的 catch 函式用於處理異常。
  */
/*
 但是請注意以下兩點:
 resolve 和 reject 的作用域只有起始函式,不包括 then 以及其他序列
 resolve 和 reject 並不能夠使起始函式停止執行,別忘了 return。
 */
//上述的 "計時器" 程式看上去比函式瀑布還要長,所以我們可以將它的核心部分寫成一個 Promise 函式:
function print(delay, message) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      console.log(message);
      resolve();
    }, delay);
  });
}
print(1000, "First")
  .then(function () {
    return print(4000, "Second");
  })
  .then(function () {
    print(3000, "Third");
  });
//將程式碼變得更好看
async function asyncFunc() {
  await print(1000, "First");
  await print(4000, "Second");
  await print(3000, "Third");
}
asyncFunc();
//非同步函式 async function 中可以使用 await 指令,
//await 指令後必須跟著一個 Promise,
//非同步函式會在這個 Promise 執行中暫停,直到其執行結束再繼續執行。

相關文章