简体   繁体   English

Apollo Server 中解析器和突变之间的共享逻辑

[英]Share logic between resolvers and mutations in Apollo Server

Here is my resolver file:这是我的解析器文件:

import { gql } from 'apollo-server-express'
import * as db from '../database'

export const typeDefs = gql`
    extend type Query {
        getFoos(): Foo
    }

    type Foo {
        id: ID!
        missingBar: [String]
    }

    input addBarInput {
        fooId: ID!
        barId: ID!
    }

    extend type Mutation {
        addBar(input: addBarInput): Foo
        startFoo(fooId: ID!): Foo
    }
`

export const resolvers = {
    Query: {
        getFoos: async () => db.foo.findAll({include: [db.bar]}),
    },
    Foo: {
        missingBar: async (obj, args, context, info) => {
            // here starts the relevant part of code
            const someBarIds = await db.some_table.findAll({
                where: {bar_id: obj.bar_id},
            }).map(el => el.bar_id)

            const otherBarIds = await db.other_table.findAll({
                where: {id: obj.bars.map(b => b.id)},
            }).map(el => el.id)

            const missingBarIds = someBarIds.filter(x => !otherBarIds.includes(x));
            // here ends the relevant part of code

            return await db.instruments.findAll({where: {id: missingInstrumentsIds}}).map(instrument => instrument.name)
        },
    },
    Mutation: {
        addBar: async (prev, { input }) => {
            const foo = await db.foo.findByPk(input.fooId)

            const bar = await db.users.findByPk(input.userId)
            await bar.setBar(foo)

            return foo
        },
        startFoo: async (prev, { input }) => {
            const foo = await db.foo.findByPk(input.fooId)

            // here I would like to have the code from missingBar without copypasting it
            // then I need to do more logic (irrelevant for this question) using that missingBarIds array

            return foo
        },
    }
}

As a note, I don't think the precise Sequelize logic in the missingBar resolver is important to the core of the question so I simplified it.请注意,我认为missingBar解析器中精确的 Sequelize 逻辑对问题的核心并不重要,因此我对其进行了简化。 The gist of it is that I want to execute an update on the DB only if all the required elements have been added to foo , and that check is performed with the exact same logic as the one in the missingBar resolver.它的要点是,只有当所有必需的元素都已添加到foo ,我才想对数据库执行更新,并且该检查的执行逻辑与missingBar解析器中的逻辑missingBar

Is there any way to share parts of the logic between different mutations and resolvers?有没有办法在不同的突变和解析器之间共享部分逻辑? Ideally, declaring a function somewhere and using it in both places?理想情况下,在某处声明一个函数并在两个地方使用它?

This hypothetic function's only parameter in this case would be an instance of the foo object (which is a Sequelize model, but again I don't think that's really relevant in this case), and the return value would be that missingBarIds array.在这种情况下,这个假设函数的唯一参数将是foo对象的一个​​实例(这是一个 Sequelize 模型,但我再次认为在这种情况下这并不重要),并且返回值将是missingBarIds数组。

At a high level, you can just write a function and use it in both resolvers.在高层次上,您可以只编写一个函数并在两个解析器中使用它。 If you don't want to have it in the same module, put it in a different module and import it.如果你不想把它放在同一个模块中,把它放在不同的模块中并导入它。 There's nothing wrong with that.没有什么不对的。

That said, since you're using Sequelize, you can add both static and instance methods to your model class.也就是说,由于您使用的是 Sequelize,您可以将静态方法和实例方法添加到模型类中。

A static method would be written like this:静态方法可以这样写:

Foo.doSomething = function doSomething () {
  ...
}

and called using the model class:并使用模型类调用:

Foo.doSomething()

An instance method would be written like this:一个实例方法可以这样写:

Foo.prototype.doSomething = function doSomething () {
  ...
}

and then called on an instance of the class :然后调用类的一个实例

const foo = await Foo.findOne()
foo.doSomething()

Note that when you define an instance method, as long as you don't use an arrow function, this will refer to the instance itself.请注意,当您定义实例方法时,只要不使用箭头函数, this将引用实例本身。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM