使用 Apollo 客户端,由于 GraphQL 请求(HTTP 代码 500)不成功,Next.js 中的 SSR 崩溃

Sir*_*haa 5 apollo reactjs graphql next.js apollo-client

嗯,我有点矮胖。我会尽力尽可能清楚地解释我的问题。

我使用 Apollo 客户端来执行 GraphQL 查询。我也使用 NextJS。出于 SEO 原因,我有一个页面需要在服务器端呈现。

所以我有一个getProductFromSlug函数可以让我执行我的请求。

export const getProductFromSlug = async (slug: string) => {
  try {
    const { data, error } = await apolloClient.query<{
      product: Product
    }>({
      query: GET_PRODUCT_BY_SLUG_QUERY,
      variables: {
        slug,
      },
    })

    if (error) {
      return { errors: [error.message] }
    }

    if (!('product' in data) || data.product === null) {
      return { errors: ['Product with specified url not found'] }
    }

    return {
      data,
    }
  } catch (error) {
    // @ts-ignore
    const formattedErrors: ApolloError = isApolloError(error)
      ? error.graphQLErrors.map((error) => error.message)
      : [`Unhandled error : ${error}`]

    return {
      errors: formattedErrors,
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

这里是getServerSideProps向页面传递数据

export const getServerSideProps = async (
  context: GetServerSidePropsContext
) => {
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
  // @ts-ignore
  const requestData = await getProductFromSlug(context.params.slug as string)
  return 'errors' in requestData
    ? { notFound: true, props: requestData }
    : { props: requestData }
}
Run Code Online (Sandbox Code Playgroud)

问题是,当我从端点收到 HTTP 代码 500 时,SSR 崩溃,在 Vercel 上,它会导致无服务器崩溃错误。

错误:响应不成功:收到状态代码 500 生成页面时发生此错误。任何控制台日志都将显示在终端窗口中

如果需要,这是我的入口点(_app.tsx):

function MyApp(props: AppProps) {
  return (
    <ApolloProvider client={apolloClient}>
      <RecoilRoot>
        <RecoilNexus />
        <AuthenticationFromStorage />
        <Layout>
          <props.Component {...props.pageProps} />
        </Layout>
      </RecoilRoot>
    </ApolloProvider>
  )
}
Run Code Online (Sandbox Code Playgroud)

您可以在这里看到我的 Apollo 客户端:https://gist.github.com/SirMishaa/d67e7229307b77b43a0b594d0c9e6943

yarn run dev(next dev -p 3005)的堆栈跟踪:

ServerError: Response not successful: Received status code 500
    at Object.throwServerError (C:\Users\misha\Documents\dev\rekk-next\node_modules\@apollo\client\link\utils\utils.cjs:45:17)
    at C:\Users\misha\Documents\dev\rekk-next\node_modules\@apollo\client\link\http\http.cjs:31:19
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
error - uncaughtException: ServerError: Response not successful: Received status code 500
error Command failed with exit code 1.
Run Code Online (Sandbox Code Playgroud)

注意在 try 和 catch 范围内尝试使用 console.log 后,它在 Next SSR 控制台中没有显示任何内容,因此由于某种原因没有捕获 Apollo 的内部错误。

我感谢您的帮助,谢谢!

在此输入图像描述

die*_*edu 2

更新

问题是,当出现错误时,PusherLink没有继续在链中执行。添加errorcomplete处理程序解决了问题。

      forward(operation).subscribe({
        next: (data) => {
          ...
          this.subscribeToChannel(subscriptionChannel, observer)
        },
        // these two were missing
        error: (error) => observer.error(error),
        complete: () => observer.complete(),
      })
Run Code Online (Sandbox Code Playgroud)

JIC,我还添加了一个缺失条件,作为参考的另一个链接的代码有

    subscribeObservable.subscribe = (observerOrNext, onError, onComplete) => {
      if (typeof(observerOrNext) == "function") {
        prevSubscribe(observerOrNext, onError, onComplete)
      } else {
        prevSubscribe(observerOrNext)
      }
Run Code Online (Sandbox Code Playgroud)

旧答案

catch 块内的代码可能会抛出错误,这就是问题所在。我不确定这个条件Array.isArray(apolloError),也许你的意思是Array.isArray(apolloError.graphQLErrors)

您可以尝试让该isApolloError实用程序变得更清晰一些,并从 TS 类型中获得一些提示。

      forward(operation).subscribe({
        next: (data) => {
          ...
          this.subscribeToChannel(subscriptionChannel, observer)
        },
        // these two were missing
        error: (error) => observer.error(error),
        complete: () => observer.complete(),
      })
Run Code Online (Sandbox Code Playgroud)