Skip to content

Allow promises to be returned in a field in the resolver of connection #853

@shreyas44

Description

@shreyas44

The below example would return a type error because the return type of the edges field is expected to be {cursor: string, node: Bar} and Promise<{cursor: string, node: Bar}> is not allowed. However, a query that requests for those edges will resolve without any error.

Why return a Promise in the getter of edges in the first place?

Say, we need to get a list of items from a database and parse that through a utility function that creates a cursor for that record. If we directly await the query to get the list of items, then we lose the ability to batch the requests using something like dataloader, or Prismas Fluent API (which uses the dataloader pattern). Instead, we can return a promise for the edges field that waits for the response from the database, parse that through our utility function to get the cursor, and resolve the promise.

An alternative is to just use the nodes() function, but then implementing a resolver for the entire connection wouldn't be possible in this scenario.

import { ApolloServer } from "apollo-server"
import { connectionPlugin, makeSchema, objectType, queryField } from "nexus"

const bars = [
  {
    cursor: "cursor1",
    node: {
      id: "1",
      barField1: "abcd",
      barField2: "abcdef",
    }
  },
  {
    cursor: "cursor2",
    node: {
      id: "2",
      barField1: "asdf",
      barField2: "asdfasdf",
    }
  }
]

const Foo = objectType({
  name: "Foo",
  definition(t) {
    t.nonNull.id("id")
    t.nonNull.string("fooField1")
    t.nonNull.string("fooField2")
   
   // --- Error in this part ---
    t.connectionField("bars", {
      type: "Bar",
      resolve() {
        return {
          get edges() {
            return new Promise(resolve => {
              resolve(bars)
            })
          }
        }
      }
    })
  }
})

const Bar = objectType({
  name: "Bar",
  definition(t) {
    t.nonNull.id("id")
    t.nonNull.string("barField1")
    t.nonNull.string("barField2")
  }
})

const fooQuery = queryField("foo", {
  type: "Foo",
  resolve() {
    return {
      id: "12345",
      fooField1: "qwrew",
      fooField2: "14123"
    }
  }
})

const schema = makeSchema({
  types: [Foo, Bar, fooQuery],
  plugins: [connectionPlugin()]
})

I'm sorry for the bad example, let me know if you'd like a better one 🙂

Metadata

Metadata

Assignees

No one assigned

    Labels

    scope/typesHaving to do with typestype/bugSomething is not working the way it should

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions