Express js middleware res.locals после следующего - PullRequest
0 голосов
/ 30 апреля 2020

Я реализовал часть промежуточного программного обеспечения (для кэширования) следующим образом (тривиализировано из реального примера):

import asyncHandler from 'express-async-handler';
import cache from '../cache';

export async function cacheMiddleware(req, res, next) {

  // Check if present in cache
  res.locals.fromCache = cache.get(res.locals.params.cacheKey);

  // Call subsequent middleware, but DO NOT return
  next();

  // After subsequent middleware chain, Update the cache if needed
  if (res.locals.accessGranted === true) {
    cache.set(res.locals.params.cacheKey, true);
  }

}

export default asyncHandler(cacheMiddleware);

В последующем промежуточном программном обеспечении я использую res.locals.fromCache, чтобы определить, имеет ли запрос кэшированное значение. Это прекрасно работает.

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

Что меня привлекло, так это то, что я ожидал, что res.locals будет объектом ссылка и, следовательно, любые изменения, сделанные в последующем промежуточном программном обеспечении, теперь будут доступны здесь. Как вы можете видеть, в этом случае я пытаюсь получить доступ к res.locals.accessGranted (установленному в последующем промежуточном программном обеспечении), чтобы определить, нужно ли мне обновлять кэш, но это свойство не существует на res.locals в этой области. Для меня это было удивительно, я думаю, res должна быть глубокой копией!?

Есть ли лучшая практика для выполнения таких операций или есть какая-то причина вообще этого не делать? Это казалось таким аккуратным решением (и шаблоном, который я успешно использовал в подобных средах в Python) и предпочтительнее, чем наличие 2-х промежуточных программ для получения и установки кэша.

1 Ответ

2 голосов
/ 30 апреля 2020

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

проблема, которую вы видите, это состояние гонки. В данном конкретном случае next() не является блокирующим. Он говорит: «Хорошо, я закончил, Express, пожалуйста, продолжайте», и express продолжает свой веселый путь. Если вы добавите несколько журналов консоли в свою программу, вы заметите, что строки после вызова next(), вероятно, выполняются до того, как ваши более поздние обработчики успеют завершить sh, особенно если они делают asyn c вызовы в базу данных или что-то в этом роде.

Фактически вы выполняете оператор if и cache.set до того, как закончится следующий кусок промежуточного программного обеспечения, что приводит к состоянию гонки.

Я не верьте , хотя я недавно не проверял, что next() позволит вам пройти и получить обратный вызов, это означает, что вам лучше разбить это промежуточное ПО на две части. Я хотел бы, чтобы восстановление кеша происходило в качестве вашей первой функции, затем вызывало бы другие функции промежуточного программного обеспечения и, наконец, вызывало бы функцию, которая выполняет любые обновления кеша. Думайте о промежуточном программном обеспечении не как о модуле, а скорее как о простой старой функции, и это имеет гораздо больше смысла, чем одна перегруженная функция промежуточного программного обеспечения.

Так что теперь у вас будет

fetchFromCache -> [various middleware, perhaps some hefty controllers] -> updateCache
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...