5
votes

Using next.js example api-routes-apollo-server-and-client. When I'm trying to implement delay in apollo/resolvers.js this way:

export const resolvers = {
  Query: {
    viewer (_parent, _args, _context, _info) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve({ id: 1, name: 'John Smith', status: 'cached' });
        }, 1000);
      })
    }
  }
}

enter image description here

This doesn't work in SSR. The data is empty in the SSR apollo state but user data expected { id: 1, name: 'John Smith', status: 'cached' }.

I'm using that also with sequelize to fetch the data from database and it doesn't work too. I guess the reason is the same.

Maybe I'm doing something wrong.

Client-side part works fine (data are displayed after React hydratation).

If we're doing static object instead of Promise:

export const resolvers = {
  Query: {
    viewer (_parent, _args, _context, _info) {
      return { id: 1, name: 'John Smith', status: 'cached' };
    }
  }
}

Everything works fine and this puts object to initial state returned from SSR server with correct static markup...

enter image description here

What am I expecting?

I want just server render graphql requiest, finish promises, the put the data to apollo state for SSR and does the SSR for SEO purposes. Because for now if I connect to the database - it doesn't work at all (nothing's rendered. just empty page because rendering was interrupted by something).

2
Please show the calling code. ALL async functions return a promise so the caller has to use await or .then() to get the value from the returned promise. Also, return await new Promise() does nothing useful over return new Promise(). And, in fact, your function doesn't even need to be async as it finds no benefit from that either.jfriend00
@jfriend00 I know. but I'm just emulating resolver with async and await. I'm not talking about optimizations. For calling code please refer to next.js example I linked to the question. So you can edit apollo/resolvers.js with contents I sent in the question and try to run. After you run it and disable javascript you'll see that there are no server-side rendered contents after gql query execution.featureoffuture
Well, if this is the example you're trying to emulate, you can't do that with an async function or a function that returns a promise. That example is a synchronous resolver. You cannot EVER get a synchronous result out of async function or out of a promise or any function that obtains its result asynchronously. Can't be done in Javascript. The caller must use await or .then() to get the value out of the promise.jfriend00
I've done enough guessing here about what you're trying to do. If this isn't enough of a response for you, then please EDIT your question to add more detail that shows exactly what you're trying to do. Or, you can wait and see if someone else who can figure out what you're trying to do comes along. If that's the case, I'll bow out.jfriend00
github.com/georgii-ivanov/next.js/tree/canary/examples/… I need this example working on server-side. This is it. Now it's working on SSR only in case Promise already resolved. (Promise.resolve(...data))featureoffuture

2 Answers

1
votes

Your code is fully correct and not problem with SSR. I test your code with next.js example api-routes-apollo-server-and-client in CSR and SSR mode. For SSR test first run npm run build and then npm start. If your problem not solved try update node.js and re-download example code and again test it.

0
votes

If you're trying to emulate the possible delay involved in resolving a remote request, or resolving promises in handlers in general, try this:

export const resolvers = {
  Query: {
    async viewer(_parent, _args, _context, _info) {
      try {
        const resp = await new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve({ id: 1, name: 'John Smith', status: 'cached' })
          }, 1000)
        })
        return resp
      } catch (err) {
        throw new Error('failed')
      }
      // return { id: 1, name: 'John Smith', status: 'cached' }
    },
  },
}

return await new Promise() doesn't work because the await keyword doesn't do anything in that case, and the object returned is still a promise, where your resolvers expect the return value to be an object.

Assigning await new Promise(...) to a variable makes sure the promise resolves, and that the variable contains the expected object prior to being returned.