首頁  >  文章  >  web前端  >  深入淺析Nodejs非同步程式設計中的Promise

深入淺析Nodejs非同步程式設計中的Promise

青灯夜游
青灯夜游轉載
2021-07-07 11:44:501702瀏覽

這篇文章帶大家了解一下Nodejs非同步程式設計中的Promise,介紹一下Promise比callback優秀在哪裡。

深入淺析Nodejs非同步程式設計中的Promise

【推薦學習:《nodejs 教學》】

什麼是Promise

Promise 是一種非同步程式設計的解決方案!

  • 目前事件循環無法得到的結果,但未來的事件循環會給你結果
  • 是一個狀態機
    • pengding
    • #resolved
    • reejectd

從程式碼看狀態流轉是怎樣的

pending 到resolve 的串流測試

(function () {
  const res = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, 500);
  });
  console.log("500ms", res);

  setTimeout(() => {
    console.log("800ms", res);
  }, 800);
})();

列印出如下內容

深入淺析Nodejs非同步程式設計中的Promise

結果是符合我們的預期的

  • 我們無法立即取得promise 的結果,此時promise處於pending狀態
  • #必須等待一段時間過後才能取得promise的結果,此時promise處於fulfilled狀態

pending 到reject 的串流測試

(function () {
  const res = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error("error"));
    }, 500);
  });
  console.log("500ms", res);

  setTimeout(() => {
    console.log("800ms", res);
  }, 800);
})();

列印出如下內容

深入淺析Nodejs非同步程式設計中的Promise

結果是符合我們的預期的

  • 我們無法立即取得promise的結果,此時promise處於pending狀態
  • 必須等待一段時間過後才能取得promise的結果,此時promise處於reject#狀態

注意:如果當pengding 狀態進入到reject 狀態,這個錯誤又沒有正確捕獲的話,這個錯誤就會被拋到JS 的全域

reslove 狀態流到reject 狀態測試

(function () {
  const res = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, 300);
    setTimeout(() => {
      reject(new Error("error"));
    }, 500);
  });
  console.log("500ms", res);

  setTimeout(() => {
    console.log("800ms", res);
  }, 800);
})();

列印出如下內容

深入淺析Nodejs非同步程式設計中的Promise

可以發現!

在300ms 的時候promise的狀態已經切換到了resolve,切換後永遠也無法到達reject狀態

  • pending 只能流到resolvereject;
  • resolvereject 不能互相流轉;

使用then,catch 捕獲promise 的結果

(function () {
  const res = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(3);
    }, 300);
  })
    .then((result) => {
      console.log("result", result);
    })
    .catch((error) => {
      console.log("error", error);
    });

  console.log("300ms", res);

  setTimeout(() => {
    console.log("800ms", res);
  }, 800);
})();

列印出如下內容

深入淺析Nodejs非同步程式設計中的Promise

    ##可以發現
  • thenpromise 的狀態流轉到
  • reslove
狀態可以拿到的結果

(function () {
  const res = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error("error-3"));
    }, 300);
  })
    .then((result) => {
      console.log("result", result);
    })
    .catch((error) => {
      console.log("error", error);
    });

  console.log("300ms", res);

  setTimeout(() => {
    console.log("800ms", res);
  }, 800);
})();

列印出如下內容深入淺析Nodejs非同步程式設計中的Promise

可以發現catchpromise 的狀態流轉到reject 狀態可以拿到的結果, 並且之前全局的JS 錯誤已經可以被

catch

捕獲到了

.then .catch 總結
  • resolved 狀態的Promise 會回呼後面的第一個.then
  • rejected 狀態的Promise 會回呼後面的第一個.catch
  • 任何一個rejected 狀態切後面沒有.catch
  • 的Promise 會造成Js 環境的全域錯誤

Promise 比起callback 優秀的地方

深入淺析Nodejs非同步程式設計中的Promise

解決非同步流程控制問題-回呼地獄我們繼續之前面試的範例

    使用Promise 改造之前的interview 函數
  • function interview() {
      return new Promise(function (resolve, reject) {
        setTimeout(() => {
          if (Math.random() > 0.4) {
            // resolve, reject 只能接受一个参数
            resolve("success");
          } else {
            reject(new Error("fail"));
          }
        }, 1000);
      });
    }
    
    (function () {
      const res = interview();
      res
        .then((result) => {
          console.log("面试成功!我笑了");
        })
        .catch((error) => {
          console.log("面试失败!我哭了");
        });
    })();
    .then 中拋出錯誤的情況測試
  • function interview() {
      return new Promise(function (resolve, reject) {
        setTimeout(() => {
          if (Math.random() > 0.4) {
            // resolve, reject 只能接受一个参数
            resolve("success");
          } else {
            reject(new Error("fail"));
          }
        }, 500);
      });
    }
    
    (function () {
      const promsie1 = interview();
    
      const promsie2 = promsie1.then((result) => {
        throw new Error("面试成功!我笑了,但是我拒绝了");
      });
    
      setTimeout(() => {
        console.log("promsie1", promsie1);
        console.log("promsie2", promsie2);
      }, 800);
    })();
  • #以上程式碼可以看出,**.then
  • 回傳一個全新的Promise, 此Promise 的結果狀態是由
.then

的回呼函數的結果來決定的

如果回呼函數最終是深入淺析Nodejs非同步程式設計中的Promisethrow

, 則進入rejected############如果回呼函數最終是###return###,則進入resolved###############.catch中正常值的狀況測試######
function interview() {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      if (Math.random() > 0) {
        // resolve, reject 只能接受一个参数
        resolve("success");
      } else {
        reject(new Error("fail"));
      }
    }, 500);
  });
}

(function () {
  const promsie1 = interview();

  const promsie2 = promsie1.catch((result) => {
    return "虽然面试失败,但我还是笑了";
  });

  setTimeout(() => {
    console.log("promsie1", promsie1);
    console.log("promsie2", promsie2);
  }, 800);
})();
##########

.catch 返回一个全新的 Promise, 此 Promise 的结果状态是由 .catch 的回调函数的结果来决定的

  • 如果回调函数最终是throw, 则进入 rejected
  • 如果回调函数最终是return,则进入 resolved

.catch,.then 里面再返回 Promise

function interview() {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      if (Math.random() > 0.4) {
        // resolve, reject 只能接受一个参数
        resolve("success");
      } else {
        reject(new Error("fail"));
      }
    }, 500);
  });
}

(function () {
  const promsie1 = interview();

  const promsie2 = promsie1
    .then((result) => {
      return new Promise(function (resolve, reject) {
        setTimeout(() => {
          resolve("面试成功!,给我400ms 总结一下");
        }, 400);
      });
    })
    .catch((result) => {
      return new Promise(function (resolve, reject) {
        setTimeout(() => {
          resolve("面试失败,给我400ms 总结一下");
        }, 400);
      });
    });

  setTimeout(() => {
    console.log("800ms promsie1", promsie1);
    console.log("800ms promsie2", promsie2);
  }, 800);

  setTimeout(() => {
    console.log("1000ms promsie1", promsie1);
    console.log("1000ms promsie2", promsie2);
  }, 1000);
})();

深入淺析Nodejs非同步程式設計中的Promise

如果在 .catch,.then 中 返回 Promise, 则会等待此 Promise 的执行结果

如果回调函数最终 return 了 Promise,该 promise 和回调函数的 return 的 Promsie 状态保持一致, 这就表示了可以 在 Promise 的链式调用里面串行的执行多个异步任务!

Promise 实现多轮面试-串行

// round 面试第几轮
function interview(round) {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      if (Math.random() > 0.4) {
        // resolve, reject 只能接受一个参数
        resolve("success");
      } else {
        const error = new Error("fail");
        reject({ round, error });
      }
    }, 500);
  });
}

(function () {
  interview(1)
    .then(() => {
      return interview(2);
    })
    .then(() => {
      return interview(3);
    })
    .then(() => {
      console.log("每轮面试都成功!我开心的笑了");
    })
    .catch((err) => {
      console.log(`第${err.round}轮面试失败了`);
    });
})();

Promise 的 .then .catch 把回调地狱变成了一段线性的代码!

Promise 实现多加公司面试-并行

// round 面试第几轮
function interview(name) {
  return new Promise(function (resolve, reject) {
    setTimeout(() => {
      if (Math.random() > 0.4) {
        // resolve, reject 只能接受一个参数
        resolve("success");
      } else {
        const error = new Error("fail");
        reject({ name, error });
      }
    }, 500);
  });
}

(function () {
  Promise.all([interview("tenxun"), interview("ali"), interview("baidu")])
    .then(() => {
      console.log("每家公司都面试成功了");
    })
    .catch((err) => {
      console.log(`面试${err.name}失败了`);
    });
})();

更多编程相关知识,请访问:编程视频!!

以上是深入淺析Nodejs非同步程式設計中的Promise的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除