我需要帮助解释一段代码。
我一直在尝试学习如何使用 jwt 以及返回 token 和刷新 token 对用户进行身份验证。
这是一次有趣的旅程,我遇到了这个 repository据我所知,用户添加了一个扩展/链函数,它结合了多个 graphql 解析器:
// I don't understand this function
const createResolver = (resolver) => {
const baseResolver = resolver;
baseResolver.createResolver = (childResolver) => {
const newResolver = async (parent, args, context, info) => {
await resolver(parent, args, context, info);
return childResolver(parent, args, context, info);
};
return createResolver(newResolver);
};
return baseResolver;
};
export const requiresAuth = createResolver((parent, args, context) => {
if (!context.user || !context.user.id) {
throw new Error('Not authenticated');
}
});
export const requiresAdmin = requiresAuth.createResolver((parent, args, context) => {
if (!context.user.isAdmin) {
throw new Error('Requires admin access');
}
});
它是这样使用的:
Query: {
getBook: requiresAuth.createResolver((parent, args, { models }, info) =>
// do something fun
),
}
我不明白 createResolver 函数,我想问的是这是否是某种编程范例,其中有一些我可以阅读并更好地理解的文章。
谷歌搜索我确实找到了 graphql-resolvers
据我所知做同样的事情但在这种情况下,我需要安装另一个我想避免但同时时间,我不想使用我不完全理解的功能。
编辑:
我对函数的理解/我认为我理解的:
通过调用一个函数将多个函数链接在一起,然后在该函数内部传入一个新函数:requiresAuth.createResolver
在函数本身内部,我无法弄清楚。
我们得到一个新变量 baseResolver
我们链接一个新的 createResolver
然后我们递归地调用父函数。
我猜我无法理解这个流程。
最佳答案
我冒昧地重命名了一些东西,因为现有的名称非常困惑。
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
时,都会创建一个新的异步 lambda 函数(wrapper
)。 wrapper
关闭 resolver
和 nextResolver
。最终运行时,wrapper
会调用resolver
,等待结果,然后调用nextResolver
,返回结果。
wrapper
然后传递给 augment
以向其添加 .add
函数(以启用链接)。这个新的 add
函数关闭提供给 augment
的参数(即 wrapper
)。返回增强的 wrapper
函数。
因此,当随后调用 .add
时,resolver
参数是调用 .add< 的
在以前的解析器上。所以:wrapper
函数
await resolver(parent, args, context, info)
return nextResolver(parent, args, context, info)
...将等待先前创建的wrapper
函数,然后调用最新的nextResolver
。
通过这种方式,对 .add
的连续调用构建了一个异步函数链。
当您想要运行链时,您可以简单地调用返回的函数,忽略其上的 .add
属性。
请注意,每个解析器都会传递相同的参数,以避免用户担心将它们传递到链中。
函数可以重写为:
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 }
关于javascript - 这个解析器扩展功能是如何工作的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60951440/