Использование Async/await в Express | Кодементор

Вы заметили, что пишете много асинхронного кода в обработчиках экспресс-запросов? Это нормально, потому что вам нужно взаимодействовать с базой данных, файловой системой и другими API.

Когда у вас так много асинхронного кода, полезно использовать Async/await. Это делает ваш код более понятным.

Сегодня я хочу рассказать, как использовать async/await в обработчике экспресс-запросов.

Примечание. Прежде чем продолжить, вам нужно знать, что такое Async/await. Если вы не знаете, вы можете прочитать эта статья Чтобы получить больше информации.

Использование Async/await с обработчиком запросов

Чтобы использовать Async/await, вам нужно использовать async ключевое слово при определении обработчика запросов. (Примечание: эти обработчики запросов называются «контроллерами». Я предпочитаю называть их обработчиками запросов, потому что обработчики запросов являются более явными).

app.post('/testing', async (req, res) => {
  // Do something here 
})

Как только у вас есть async ключевое слово, вы можете await что-то сразу в вашем коде.

app.post('/testing', async (req, res) => {
  const user = await User.findOne({email: req.body.email})
})

Обработка асинхронных ошибок

Допустим, вы хотите создать пользователя с помощью POST-запроса. Чтобы создать пользователя, вам нужно передать firstName и email адрес. Ваша схема Mongoose выглядит так:

const userSchema = new Schema({
  email: {
    type: String,
    required: true,
    unique: true,
  },
  firstName: {
    type: String,
    required: true,
  }
})

Вот ваш обработчик запросов:

app.post('/signup', async(req, res) => {
  const { email, firstName } = req.body 
  const user = new User({ email, firstName })
  const ret = await user.save()
  res.json(ret)
})

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

fetch('/signup', {
  method: 'post'
  headers: { 'Content-Type': 'application/json' } 
  body: JSON.stringify({
    firstName: 'Zell'
  })
}

Этот запрос приводит к ошибке. К сожалению, Express не сможет обработать эту ошибку. Вы получите такой журнал:

Предупреждение об отклонении необработанного обещания.

Чтобы обработать ошибку в асинхронной функции, вам нужно сначала перехватить ошибку. Вы можете сделать это с try/catch.

app.post('/signup', async(req, res) => {
  try {
    const { email, firstName } = req.body 
    const user = new User({ email, firstName })
    const ret = await user.save()
    res.json(ret)
  } catch (error) {
    console.log(error)
  }
})

Вывод ошибки в консоль.

Затем вы передаете ошибку в обработчик ошибок Express с параметром next аргумент.

app.post('/signup', async(req, res, next) => {
  try {
    const { email, firstName } = req.body 
    const user = new User({ email, firstName })
    const ret = await user.save()
    res.json(ret)
  } catch (error) {
    // Passes errors into the error handler
    return next(error)
  }
})

Если вы еще не написали собственный обработчик ошибок, Express обработает ошибку за вас с помощью обработчика ошибок по умолчанию. (Хотя я рекомендую вам написать собственный обработчик ошибок. Вы можете узнать больше об этом здесь).

Обработчик ошибок Express по умолчанию:

  1. Установите статус HTTP на 500
  2. Отправить текстовый ответ обратно запрашивающей стороне
  3. Запишите текстовый ответ в консоли

Отправляет текстовый ответ обратно на запросЯ использовал Postman для отправки запроса на мой сервер. Вот текстовый ответ от сервера.

Записывает текстовый ответ в консоль.Обратите внимание на журнал состояния HTTP 500 на этом изображении. Это говорит мне, что обработчик Express по умолчанию изменил статус HTTP на 500. Журнал принадлежит Моргану. E подробно рассказал о Моргане здесь.

Обработка двух или более асинхронных ошибок

Если вам нужно справиться с двумя await заявления, вы можете написать этот код:

app.post('/signup', async(req, res, next) => {
  try {
    await firstThing()
  } catch (error) {
    return next(error)
  }

  try {
    await secondThing()
  } catch (error) {
    return next(error)
  }
})

Это не нужно. Если firstThing приводит к ошибке, запрос будет немедленно отправлен обработчику ошибок. Вы бы не инициировали вызов для secondThing. Если secondThing приводит к ошибке, firstThing не вызвал бы ошибку.

Это означает: обработчику ошибок будет отправлена ​​только одна ошибка. Это также означает, что мы можем обернуть все await заявления в ОДНОМ try/catch утверждение.

app.post('/signup', async(req, res, next) => {
  try {
    await firstThing()
    await secondThing()
  } catch (error) {
    return next(error)
  }
})

Убираться

Отстойно иметь try/catch оператор в каждом обработчике запросов. Они делают обработчик запроса более сложным, чем он должен быть.

Простой способ — изменить try/catch в обещание. Это кажется более дружелюбным.

app.post('/signup', async(req, res, next) => {
  function runAsync () {
    await firstThing()
    await secondThing()
  }

  runAsync()
    .catch(next)
})

Но это муторно писать runAsync для каждого экспресс-обработчика. Мы можем абстрагировать его в функцию-оболочку. И мы можем прикрепить эту функцию-оболочку к каждому обработчику запросов.

function runAsyncWrapper (callback) {
  return function (req, res, next) {
    callback(req, res, next)
      .catch(next)
  }
}

app.post('/signup', runAsyncWrapper(async(req, res) => {
    await firstThing()
    await secondThing()
})

Экспресс-асинхронный обработчик

Вам не нужно писать runAsyncWrapper каждый раз, когда вы пишете экспресс-приложение. Алексей Баженов создал пакет под названием экспресс-асинхронный обработчик это делает работу немного более надежным способом. (Это гарантирует next всегда последний аргумент).

Использовать express-async-handlerвы должны сначала установить его:

npm install express-async-handler --save

Использование его в вашем приложении:

const asyncHandler = require('express-async-handler') 

app.post('/signup', asyncHandler(async(req, res) => {
    await firstThing()
    await secondThing()
})

я не люблю писать asyncHandler. Это довольно долго. Мое очевидное решение — сократить asyncHandler к ash.

Если вы любите, вы можете рассмотреть возможность использования @awaitjs/экспресс по Валерий Карпов. Он добавляет такие методы, как getAsync а также postAsync для выражения, поэтому вам не нужно использовать express-async-handler.

Спасибо за чтение. Эта статья изначально была размещена на мой блог. Подписаться на моя рассылка если вы хотите больше статей, которые помогут вам стать лучшим разработчиком внешнего интерфейса.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *