UnhandledPromiseRejectionWarning:错误:在 ApolloServer 调用 `server.applyMiddleware()` 之前必须`await server.s

Posted

技术标签:

【中文标题】UnhandledPromiseRejectionWarning:错误:在 ApolloServer 调用 `server.applyMiddleware()` 之前必须`await server.start()`【英文标题】:UnhandledPromiseRejectionWarning: Error: You must `await server.start()` before calling `server.applyMiddleware()` at ApolloServer 【发布时间】:2021-10-09 07:32:15 【问题描述】:

我正在尝试启动我的 nestJs 服务器,但它一直给我这个错误:

UnhandledPromiseRejectionWarning:错误:您必须先await server.start(),然后再调用server.applyMiddleware() 在 ApolloServer

我什至不知道从哪里调试,因为我还是 NestJs 和 GraphQL 的新手。

【问题讨论】:

在不知道您当前如何运行这些东西的情况下,我们无法为您提供帮助。 【参考方案1】:

这是一个已知错误,有一个未解决的问题and a merged PR to fix it。目前,您可以降级到apollo-server-express@^2

【讨论】:

非常感谢。现在工作正常 看起来有计划发布@nestjs/graphql@9 来解决这个问题。根据问题,这个重大突破将在@nestjs/core@nestjs/common 重大突破到9 之前很久。但至于何时,我不能说 谢谢@JayMcDoniel 这对我也有用:)【参考方案2】:

完整的工作代码是:

const express = require("express");
const  ApolloServer  = require("apollo-server-express");
const http = require("http");

const app = express();

const typeDefs = `
    type Query
        totalPosts: Int!
    
`;
const resolvers = 
    Query: 
        totalPosts: () => 100,
    ,
;
let apolloServer = null;
async function startServer() 
    apolloServer = new ApolloServer(
        typeDefs,
        resolvers,
    );
    await apolloServer.start();
    apolloServer.applyMiddleware( app );

startServer();
const httpserver = http.createServer(app);

app.get("/rest", function (req, res) 
    res.json( data: "api working" );
);

app.listen(4000, function () 
    console.log(`server running on port 4000`);
    console.log(`gql path is $apolloServer.graphqlPath`);
);

【讨论】:

这无需更改 libray 版本即可工作,但不需要以下行: const httpserver = http.createServer(app);【参考方案3】:

我在升级Ben Awad's Graphql-Next-Typeorm[...] stack 时遇到了这个问题,只需在服务器启动中添加等待即可修复警告

const apolloServer = new ApolloServer(
    introspection: true,
    schema: await buildSchema(
      resolvers: [__dirname + '/resolvers/**/*.js'],
      validate: false
    ),
    context: ( req, res ) => (
      req,
      res,
      redis: redisClient
    ),
    formatError
  );


// added this line
  await apolloServer.start();

  apolloServer.applyMiddleware(
    app,
    cors: false
  );

【讨论】:

同样来自 Ben Awad 的课程。 cors: false 确实有帮助,但为什么要关闭 introspection 呢? @BurgerBurglar 我相信你的问题是题外话,内省设置为真,这里有更多关于内省的信息apollographql.com/docs/apollo-server/api/apollo-server/… 我在迁移文档中找不到此信息 @EricBurel 我不确定我理解你的意思或暗示,你能详细说明一下吗? 简单地说,Apollo v3 迁移文档并没有很明确地说明需要等待“开始”,或者至少我找不到相关部分,但你的回答很完美【参考方案4】:

对于 Apollo Server Express 3.0 及更高版本,您需要定义一个接收 typeDefs 和 resolvers 参数的异步函数,然后将服务器分配给与之前相同的 Apollo 初始化,如 here 所示

async function startApolloServer(typeDefs, resolvers)
    const server = new ApolloServer(typeDefs, resolvers)
    const app = express();
    await server.start();
    server.applyMiddleware(app, path: '/graphql');
    
    app.listen(PORT, () => 
    console.log(`Server is listening on port $PORT$server.graphqlPath`);
)


startApolloServer(typeDefs, resolvers);

【讨论】:

【参考方案5】:

您可以将所有内容放在异步函数中并在您的服务器(应用程序,索引...).js 中执行该函数。你也可以查看 npm 包。 https://www.npmjs.com/package/apollo-server-express 例如:

const express = require('express')
    , http = require('http')
    , path = require('path');
const  ApolloServer  = require('apollo-server-express');

async function startExpressApolloServer() 

    const  typeDefs  = require('./graphql/schemas/schema');
    const  resolvers  = require('./graphql/resolvers/resolver');

    const server = new ApolloServer( typeDefs, resolvers );
    await server.start();

    const app = express();
    
    server.applyMiddleware( app, path: '/api/graphql' );

    await new Promise(resolve => app.listen( port: 3001 , resolve));
    console.log(`Server ready at http://localhost:3001$server.graphqlPath`);
    return  server, app ;


startExpressApolloServer();

【讨论】:

+1 基本上来自文档的建议:apollographql.com/docs/apollo-server/api/apollo-server/…【参考方案6】:

另一种选择是将您的 apollo 降级到任何 2.x.x。它解决了我的问题

【讨论】:

【参考方案7】:

提前启动apollo服务器是不行的。当我必须明确使用 http/https 时会发生什么情况。请看以下案例:

  const server = new ApolloServer(
    typeDefs: [KeycloakTypeDefs, typeDefs], // 1. Add the Keycloak Type Defs
    schemaDirectives: KeycloakSchemaDirectives, // 2. Add the
    formatError: new ApolloErrorConverter(),
    resolvers: resolvers,
    context: ( req ) => 
      return makeContextWithDependencies(req);
    
  );
  server.applyMiddleware( app );

  http.createServer(app).listen(config.server.port, os.hostname());
  const options = 
    key: fs.readFileSync(config.server.ssl.keyFile, "utf8"),
    cert: fs.readFileSync(config.server.ssl.certFile, "utf8"),
    passphrase: config.server.ssl.passphrase
  ;
  https
    .createServer(options, app)
    .listen(config.server.securePort, os.hostname());
  console.log(
    "Server waiting for requests on ports: " +
      config.server.port +
      "," +
      config.server.securePort
  );

【讨论】:

如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。 - From Review【参考方案8】:

这里已经有一些很好的答案。但是我们应该知道为什么以及在哪里调用 server.start()。来自阿波罗文档 -

在调用之前总是调用 await server.start() server.applyMiddleware 并启动您的 HTTP 服务器。这允许 你通过崩溃你的来对 Apollo Server 启动失败做出反应 进程而不是开始提供流量。

【讨论】:

【参考方案9】:

在 v3 中,如果您使用 apollo-server-express,则需要启动功能https://www.apollographql.com/docs/apollo-server/api/apollo-server/#start。

你可以这样做。

const app = express()
app.use(express.urlencoded( extended: true ))
app.use(express.json())
....
export const startup = async () => 
  await server.start()
  server.applyMiddleware( app, path: `/api/$configs.region/graphql` )
  return app


// call startup in another file to get app

【讨论】:

github.com/nestjs/nest/issues/7543#issuecomment-878811893

以上是关于UnhandledPromiseRejectionWarning:错误:在 ApolloServer 调用 `server.applyMiddleware()` 之前必须`await server.s的主要内容,如果未能解决你的问题,请参考以下文章

[Unhandled promise rejection: TypeError: null is not an object (evaluating '_reactNativeImageCropPic

等待 - 捕获错误 - UnhandledPromiseRejectionWarning

批量删除如何工作?

7月工作知识总计:

未处理的承诺拒绝 |重启命令

未处理的承诺拒绝警告(Cordova Angular)