首頁 > web前端 > js教程 > 主體

快速避坑,聊聊5個用promise的常見錯誤!

青灯夜游
發布: 2021-12-08 10:22:19
轉載
1852 人瀏覽過

這篇文章跟大家分享5個使用 promise 時的常見錯誤,幫大家快速避坑,希望對大家有幫助!

快速避坑,聊聊5個用promise的常見錯誤!

Promise 提供了一種優雅的方法來處理 JS 中的非同步操作。這也是避免「回調地獄」的解決方案。然而,並沒有太多開發人員了解其中的內容。因此,許多人在實踐中往往會犯錯。 【相關推薦:javascript學習教學

在本文中,介紹一下使用 promise 時的五個常見錯誤,希望大家能夠避免這些錯誤。

1.避免 Promise 地獄

#通常,Promise是用來避免回調地獄。但濫用它們也會導致 Promise是地獄。

userLogin('user').then(function(user){
    getArticle(user).then(function(articles){
        showArticle(articles).then(function(){
            //Your code goes here...
        });
    });
});
登入後複製

在上面的範例中,我們對 userLogingetararticleshowararticle 嵌套了三個promise。這樣複雜性將按程式碼行比例增長,它可能變得不可讀。

為了避免這種情況,我們需要解除程式碼的巢狀,從第一個then 中傳回getArticle,然後在第二個then 中處理它。

userLogin('user')
  .then(getArticle)
  .then(showArticle)
  .then(function(){
       //Your code goes here...
});
登入後複製

2. 在Promise 中使用<span style="font-size: 18px;">#try/catch</span> 區塊

通常情況下,我們使用try/catch 區塊來處理錯誤。然而,不建議在 Promise 物件中使用try/catch

這是因為如果有任何錯誤,Promise物件會在 catch 內自動處理。

ew Promise((resolve, reject) => {
  try {
    const data = doThis();
    // do something
    resolve();
  } catch (e) {
    reject(e);
  }
})
  .then(data => console.log(data))
  .catch(error => console.log(error));
登入後複製

在上面的範例中,我們在Promise 內使用了 try/catch 區塊。

但是,Promise本身會在其作用域內捕捉所有的錯誤(甚至是打字錯誤),而不需要 try/catch區塊。它確保在執行過程中拋出的所有異常都被獲取並轉換為被拒絕的 Promise。

new Promise((resolve, reject) => {
  const data = doThis();
  // do something
  resolve()
})
  .then(data => console.log(data))
  .catch(error => console.log(error));
登入後複製

注意:在 Promise 區塊中使用 .catch() 區塊是至關重要的。否則,你的測試案例可能會失敗,而且應用程式在生產階段可能會崩潰。

3. 在Promise 區塊內使用非同步函數

Async/Await 是更高階的語法,用於處理同步程式碼中的多個Promise。當我們在一個函數宣告前使用async 關鍵字時,它會傳回一個Promise,我們可以使用await 關鍵字來停止程式碼,直到我們正在等待的Promise解決或拒絕。

但是,當你把一個 Async 函數放在一個 Promise 區塊裡面時,會有一些副作用。

假設我們想要在Promise 區塊中做一個非同步操作,所以使用了 async 關鍵字,但,不巧的是我們的程式碼拋出了一個錯誤。

這樣,即使使用 catch() 區塊或在 try/catch 區塊內等待你的Promise,我們也不能立即處理這個錯誤。請看下面的例子。

// 此代码无法处理错误
new Promise(async () => {
  throw new Error(&#39;message&#39;);
}).catch(e => console.log(e.message));

(async () => {
  try {
    await new Promise(async () => {
      throw new Error(&#39;message&#39;);
    });
  } catch (e) {
    console.log(e.message);
  }
})();
登入後複製

當我在Promise區塊內遇到 async 函數時,我試圖將 async 邏輯保持在 Promise 區塊之外,以保持其同步性。 10次​​中有9次都能成功。

然而,在某些情況下,可能需要一個 async 函數。在這種情況下,也別無選擇,只能用try/catch 區塊來手動管理。

new Promise(async (resolve, reject) => {
  try {
    throw new Error(&#39;message&#39;);
  } catch (error) {
    reject(error);
  }
}).catch(e => console.log(e.message));


//using async/await
(async () => {
  try {
    await new Promise(async (resolve, reject) => {
      try {
        throw new Error(&#39;message&#39;);
      } catch (error) {
        reject(error);
      }
    });
  } catch (e) {
    console.log(e.message);
  }
})();
登入後複製

4.在建立Promise 後立即執行Promise 區塊

至於下面的程式碼片段,如果我們把程式碼片段放在呼叫HTTP請求的地方,它就會被立即執行。

const myPromise = new Promise(resolve => {
  // code to make HTTP request
  resolve(result);
});
登入後複製

原因是這段程式碼被包裹在一個Promise建構函式中。然而,有些人可能會認為只有在執行myPromisethen方法之後才被觸發。

然而,真相並非如此。相反,當一個Promise被創建時,回調會立即執行。

這表示在建立 myPromise 之後到達下面一行時,HTTP請求很可能已經在運行,或至少處於調度狀態。

Promises  總是急於執行程序。

但是,如果希望以後再執行 Promises,該怎麼做?如果現在不想發出HTTP請求怎麼辦?是否有什麼神奇的機制內建在 Promises 中,使我們能夠做到這一點?

答案就是使用函數。函數是一種耗時的機制。只有當開發者明確地用 () 來呼叫它們時,它們才會執行。簡單地定義一個函數還不能讓我們得到什麼。所以,讓 Promise 變得懶惰的最有效方法是將其包裹在一個函數中!

const createMyPromise = () => new Promise(resolve => {
  // HTTP request
  resolve(result);
});
登入後複製

对于HTTP请求,Promise 构造函数和回调函数只有在函数被执行时才会被调用。所以现在我们有一个懒惰的Promise,只有在我们需要的时候才会执行。

5. 不一定使用 Promise.all() 方法

如果你已经工作多年,应该已经知道我在说什么了。如果有许多彼此不相关的 Promise,我们可以同时处理它们。

Promise 是并发的,但如你一个一个地等待它们,会太费时间,Promise.all()可以节省很多时间。

记住,Promise.all() 是我们的朋友
const { promisify } = require(&#39;util&#39;);
const sleep = promisify(setTimeout);

async function f1() {
  await sleep(1000);
}

async function f2() {
  await sleep(2000);
}

async function f3() {
  await sleep(3000);
}


(async () => {
  console.time(&#39;sequential&#39;);
  await f1();
  await f2();
  await f3();
  console.timeEnd(&#39;sequential&#39;);  
})();
登入後複製

上述代码的执行时间约为 6 秒。但如果我们用 Promise.all() 代替它,将减少执行时间。

(async () => {
    console.time(&#39;concurrent&#39;);
    await Promise.all([f1(), f2(), f3()]);
    console.timeEnd(&#39;concurrent&#39;); 
  })();
登入後複製

总结

在这篇文章中,我们讨论了使用 Promise 时常犯的五个错误。然而,可能还有很多简单的问题需要仔细解决。

如果你还有更多相关的错误,欢迎留言一起讨论。

英文原文地址:https://blog.bitsrc.io/5-common-mistakes-in-using-promises-bfcc4d62657f

作者:Ravidu Perera

更多编程相关知识,请访问:编程入门!!

以上是快速避坑,聊聊5個用promise的常見錯誤!的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!