这个解析器扩展功能如何工作?

Cod*_*tle 3 javascript graphql apollo-server

我需要帮助解释一段代码。

我一直在尝试学习如何使用 jwt 对用户进行身份验证并返回令牌和刷新令牌。

这是一次有趣的旅程,我遇到了这个 存储库,其中用户添加了一个扩展/链函数,据我所知,它结合了多个 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');
  }
});
Run Code Online (Sandbox Code Playgroud)

它的用法如下:

Query: { 
    getBook: requiresAuth.createResolver((parent, args, { models }, info) =>
       // do something fun
    ),
}
Run Code Online (Sandbox Code Playgroud)

我不理解 createResolver 函数,我想问这是否是某种类型的编程范例,其中有一些文章我可以更好地阅读和理解它。

谷歌搜索我确实发现graphql-resolvers,据我所知,它做了同样的事情,但在这种情况下,我需要安装另一个我想避免的包,但同时,我不想使用我想要的功能不完全理解。

编辑:

我对该功能的理解/认为我理解:

通过调用一个函数,然后在该函数内部传入一个新函数,将多个函数链接在一起:requiresAuth.createResolver 在函数本身内部,我无法弄清楚它。我们得到一个新变量baseResolver,我们将其链接到一个新createResolver 变量,然后递归调用父函数。

我猜我无法理解这个流程。

Ben*_*Ben 5

我冒昧地重命名了一些东西,因为现有的名称非常混乱。

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
}
Run Code Online (Sandbox Code Playgroud)

在该过程的每一步中,.add都会将一个方法添加到返回的函数中,以启用链接,如下所示:

augment(resolver1).add(resolver2).add(resolver3)...
Run Code Online (Sandbox Code Playgroud)

每次.add调用时,wrapper都会创建一个新的异步 lambda 函数 ( )。和wrapper都闭合。最终运行时,会调用,等待结果,然后调用,返回结果。resolvernextResolverwrapperresolvernextResolver

wrapper然后传递给它augment以添加一个函数(以启用链接)。.add这个新add函数结束提供给augment(即wrapper) 的参数。wrapper返回增强函数。

因此,当.add随后调用时,resolver参数是wrapper调用.add前一个解析器的函数。所以:

await resolver(parent, args, context, info)
return nextResolver(parent, args, context, info)
Run Code Online (Sandbox Code Playgroud)

...将等待先前创建的wrapper函数,然后调用最新的nextResolver.

这样,连续调用就.add构造了一个异步函数链。

当你想要运行链时,你可以简单地调用返回的函数,忽略.add它的属性。

请注意,每个解析器都会传递相同的参数,以避免用户不得不担心将它们传递到链上。

该函数可以重写为:

augment(resolver1).add(resolver2).add(resolver3)...
Run Code Online (Sandbox Code Playgroud)

...或者:

await resolver(parent, args, context, info)
return nextResolver(parent, args, context, info)
Run Code Online (Sandbox Code Playgroud)

...或者:

const augment = (resolver) => {
  resolver.add = (nextResolver) => 
    augment((...args) => 
      resolver(...args)
        .then(() => nextResolver(...args)))
  return resolver
}
Run Code Online (Sandbox Code Playgroud)

  • 该网站扩展了一些可能对您有所帮助的函数式编程概念:https://dev.to/damxipo/function-programming-in-javascript-442p (2认同)