Я позволил себе переименовать некоторые вещи, потому что существующие имена очень запутаны.
const augment = (resolver) => {
resolver.add = (nextResolver) => {
const wrapper = async (parent, args, context, info) => {
await resolver(parent, args, context, info)
return nextResolver(parent, args, context, info)
}
return augment(wrapper)
}
return resolver
}
На каждом этапе пути к возвращаемой функции добавляется метод .add
, чтобы включить цепочку следующим образом:
augment(resolver1).add(resolver2).add(resolver3)...
Каждый раз, когда вызывается .add
, создается новая асинхронная c лямбда-функция (wrapper
). wrapper
закрывается как resolver
, так и nextResolver
. Когда он в конце концов будет запущен, wrapper
вызовет resolver
, дождется результата, а затем вызовет nextResolver
и вернет результат.
wrapper
затем передается в augment
для добавления .add
функция к нему (для включения цепочки). Эта новая функция add
закрывает аргумент, переданный augment
(то есть wrapper
). Возвращается расширенная функция wrapper
.
Итак, когда впоследствии вызывается .add
, аргумент resolver
является функцией wrapper
вызова .add
в предыдущем преобразователе. Итак:
await resolver(parent, args, context, info)
return nextResolver(parent, args, context, info)
... будет ожидать ранее созданную функцию wrapper
, а затем вызовет самую последнюю nextResolver
.
Таким образом, последовательные вызовы конструкции .add
цепочка асин c функций.
И когда вы хотите запустить цепочку, вы можете просто вызвать возвращенную функцию, игнорируя свойство .add
для нее.
Обратите внимание, что каждый resolver передается те же аргументы, чтобы пользователю не приходилось беспокоиться о передаче их по цепочке.
Функция может быть переписана как:
const augment = (resolver) => {
resolver.add = (nextResolver) =>
augment((...args) =>
resolver(...args)
.then(() => nextResolver(...args)))
return resolver
}
... или:
const inSequence = (resolvers) =>
(...args) =>
resolvers.reduce((acc, el) =>
acc.then(() => el(...args)), Promise.resolve())
const getBook = inSequence([auth, admin, getBookResolver])
const query = { getBook }
... или:
const inSequence = (resolvers) =>
async (...args) => {
for(let el of resolvers) {
await el(...args)
}
}
const getBook = inSequence([auth, admin, getBookResolver])
const query = { getBook }