Home >Web Front-end >JS Tutorial >Quickly avoid pitfalls and talk about 5 common mistakes in using promises!

Quickly avoid pitfalls and talk about 5 common mistakes in using promises!

青灯夜游
青灯夜游forward
2021-12-08 10:22:191896browse

This article will share with you 5 common mistakes when using promises to help you avoid pitfalls quickly. I hope it will be helpful to you!

Quickly avoid pitfalls and talk about 5 common mistakes in using promises!

#Promise provides an elegant way to handle asynchronous operations in JS. This is also a solution to avoid "callback hell". However, not many developers understand what's involved. Therefore, many people tend to make mistakes in practice. [Related recommendations: javascript learning tutorial]

In this article, we introduce five common mistakes when using promises, and hope that everyone can avoid these mistakes.

1. Avoid Promise Hell

Usually, Promise is used to avoid callback hell. But abusing them can also lead to Promises being hell.

userLogin('user').then(function(user){
    getArticle(user).then(function(articles){
        showArticle(articles).then(function(){
            //Your code goes here...
        });
    });
});

In the above example, we have three nested promises for userLogin, getararticle and showararticle. This way the complexity will grow in proportion to the lines of code and it may become unreadable.

To avoid this, we need to unnest the code, return getArticle from the first then, and then in the second then to handle it.

userLogin('user')
  .then(getArticle)
  .then(showArticle)
  .then(function(){
       //Your code goes here...
});

2. Use <span style="font-size: 18px;">try/catch</span> block

in Promise

Normally, we use try/catch blocks to handle errors. However, using try/catch within a Promise object is not recommended.

This is because if there are any errors, the Promise object will be automatically handled within 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));

In the above example, we used the try/catch block inside the Promise.

However, Promise itself will catch all errors (even typos) within its scope without the need for a try/catch block. It ensures that all exceptions thrown during execution are caught and converted into rejected Promises.

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

Note: It is crucial to use the .catch() block within a Promise block. Otherwise, your test cases may fail and the application may crash during the production phase.

3. Use asynchronous functions within Promise blocks

Async/Await is a more advanced syntax, Used to handle multiple Promises in synchronous code. When we use the async keyword before a function declaration, it will return a Promise. We can use the await keyword to stop the code until the Promise we are waiting for is resolved or rejected. .

However, when you put an Async function inside a Promise block, there will be some side effects.

Suppose we want to do an asynchronous operation in the Promise block, so we use the async keyword, but unfortunately our code throws an error.

This way, even if you use a catch() block or wait for your Promise inside a try/catch block, we cannot handle the error immediately. Please see the example below.

// 此代码无法处理错误
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);
  }
})();

When I encounter an async function inside a Promise block, I'm trying to keep the async logic outside the Promise block to keep it synchronized. It works 9 times out of 10.

However, in some cases, an async function may be required. In this case, there is no choice but to manage it manually using try/catch blocks.

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. Execute the Promise block immediately after creating the Promise

As for the following code snippet, if we put the code snippet in the call HTTP Where requested, it will be executed immediately.

const myPromise = new Promise(resolve => {
  // code to make HTTP request
  resolve(result);
});

The reason is that this code is wrapped in a Promise constructor. However, some may think that it is only triggered after the then method of myPromise is executed.

However, the truth is not so. In contrast, when a Promise is created, the callback is executed immediately.

This means that by the time the following line is reached after establishing myPromise, the HTTP request is most likely already running, or at least in a scheduled state.

Promises are always eager to execute the process.

But what should you do if you want to execute Promises in the future? What if I don't want to make an HTTP request now? Is there some magical mechanism built into Promises that allows us to do this?

The answer is to use functions. Functions are a time-consuming mechanism. They will only execute if the developer explicitly calls them with (). Simply defining a function doesn't get us anywhere. So, the most efficient way to make a Promise lazy is to wrap it in a function!

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

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

The above is the detailed content of Quickly avoid pitfalls and talk about 5 common mistakes in using promises!. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:segmentfault.com. If there is any infringement, please contact admin@php.cn delete