5 распространенных ошибок при использовании промисов, сколько их у вас есть!

JavaScript

Автор: Равиду Перера Переводчик: Front-end Xiaozhi Источник: среда

Есть мечта, есть галантерейные товары, поиск в WeChat【Переезд в мир】Обратите внимание на эту мудрость чаши-щетки, которая все еще моет посуду ранним утром.

Эта статьяGitHubGitHub.com/QQ449245884…Включено, и есть полные тестовые площадки, материалы и мой цикл статей для интервью с производителями первой линии.

Промисы предоставляют элегантный способ обработки асинхронных операций в JS. Это также решение, позволяющее избежать «ада обратных вызовов». Однако не многие разработчики понимают, что в нем. Поэтому многие люди склонны ошибаться на практике.

В этой статье я расскажу о пяти распространенных ошибках при использовании промисов, которых, я надеюсь, вы сможете избежать.

1. Избегайте ада обещаний

Обычно промисы используются, чтобы избежать ада обратных вызовов. Но неправильное их использование также может привести к тому, что обещания станут адом.

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

В приведенном выше примере мы имеемuserLogin,getararticleа такжеshowararticleТри промиса вложены друг в друга. Эта сложность будет расти пропорционально количеству строк кода и может стать нечитаемой.

Чтобы этого избежать, нам нужно невложенность кода, начиная с первогоthenвернуться вgetArticle, то во второмthenобработать его.

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

2. Использование обещанийtry/catchКусок

Как правило, мы используем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Кусок.

Однако сами промисы будут ловить все ошибки (даже опечатки) в пределах своей области действия без необходимостиtry/catchКусок. Это гарантирует, что все исключения, возникающие во время выполнения, будут перехвачены и преобразованы в отклоненные промисы.

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— это высокоуровневый синтаксис для обработки нескольких промисов в синхронном коде. когда мы используем перед объявлением функцииasyncключевое слово, оно возвращает обещание, мы можем использоватьawaitключевое слово, чтобы остановить код до тех пор, пока обещание, которое мы ожидаем, не будет разрешено или отклонено.

Однако когда вы помещаете асинхронную функцию внутрь блока Promise, возникают некоторые побочные эффекты.

Предположим, мы хотим выполнить асинхронную операцию в блоке Promise, поэтому используйтеasyncключевое слово, но, к сожалению, наш код выдает ошибку.

Таким образом, даже используяcatch()блокировать или вtry/catchОжидая вашего обещания внутри блока, мы также не можем сразу обработать эту ошибку. См. пример ниже.

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

(async () => {
  try {
    await new Promise(async () => {
      throw new Error('message');
    });
  } catch (e) {
    console.log(e.message);
  }
})();

Когда я сталкиваюсь внутри блока Promiseasyncфункция, я пыталсяasyncЛогика хранится вне блока Promise, чтобы обеспечить его синхронизацию. Срабатывает 9 из 10 раз.

Однако в некоторых случаях аasyncфункция. В этом случае тоже нет другого выхода, кроме как использоватьtry/catchблоки для управления вручную.

new Promise(async (resolve, reject) => {
  try {
    throw new Error('message');
  } 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('message');
      } 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. Однако некоторые могут возразить, что только тогда, когдаmyPromiseизthenМетод запускается только после этого.

Однако на самом деле это не так. Вместо этого, когда создается промис, обратный вызов выполняется немедленно.

Это означает строительствоmyPromiseК тому времени, когда вы дойдете до строки ниже, HTTP-запрос, скорее всего, уже запущен или, по крайней мере, запланирован.

Обещания всегда стремятся выполнить процесс.

Но что, если вы хотите выполнить промисы позже? Что, если я не хочу сейчас делать HTTP-запросы? Есть ли какой-то магический механизм, встроенный в промисы, который позволяет нам это делать?

Ответ заключается в использовании функций. Функции — это трудоемкий механизм. только если разработчик явно использует()чтобы позвонить им, они будут выполнять. Простое определение функции не дает нам многого. Таким образом, самый эффективный способ сделать промис ленивым — обернуть его функцией!

const createMyPromise = () => new Promise(resolve => {
  // HTTP request
  resolve(result);
});

Для HTTP-запросов конструкторы Promise и обратные вызовы вызываются только при выполнении функции. Итак, теперь у нас есть ленивый промис, который выполняется только тогда, когда нам это нужно.

5. Не обязательно использовать метод Promise.all()

Если вы работали в течение многих лет, вы уже знаете, о чем я говорю. Если есть много промисов, не связанных друг с другом, мы можем обработать их все одновременно.

Обещания одновременны, но если вы будете ждать их по одному, это займет слишком много времени,Promise.all()Может сэкономить много времени.

Помните, что Promise.all() — наш друг

const { promisify } = require('util');
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('sequential');
  await f1();
  await f2();
  await f3();
  console.timeEnd('sequential');  
})();

Время выполнения приведенного выше кода составляет около6Второй. но если мы используемPromise.all()Его замена сократит время выполнения.

(async () => {
    console.time('concurrent');
    await Promise.all([f1(), f2(), f3()]);
    console.timeEnd('concurrent'); 
  })();

Суммировать

В этой статье мы обсудили пять распространенных ошибок при использовании промисов. Однако может быть много более простых проблем, требующих тщательного решения.

Если у вас есть другие связанные ошибки, пожалуйста, оставьте сообщение для совместного обсуждения.

~Конец, я человек, который пойдет домой и установит уличную палатку после выхода на пенсию.Увидимся в следующем выпуске!


Ошибки, которые могут существовать после развертывания кода, нельзя узнать в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку логов.Кстати, всем рекомендую полезный инструмент мониторинга ошибок.Fundebug.

оригинал:blog.bit SRC.IO/5-common-m…

общаться с

Статьи постоянно обновляются каждую неделю, и их можно искать в WeChat.【Переезд в мир】Сначала прочитай, ответь【Благосостояние】Вас ждет много фронтенд-видео, эта статья GitHubGitHub.com/QQ449245884…Он был записан, добро пожаловать в Star.