为什么 nexus dev 命令运行应用程序两次,如何解决?

Why nexus dev command runs app twice, and how to fix it?

我使用 nexus graphql 框架创建了超级简单的应用程序。

第一步是这样的:

https://www.nexusjs.org/#/tutorial/chapter-1-setup-and-first-query

api/app.ts我输入了代码:

const uid = require('uid')

let i = 0;

const sleep = async (ms: number) => {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, ms)
    })
}

const recurrenceFunction = async (id:string): Promise<void> => {
    i++;
    console.log(id, i);
    await sleep(2000);
    return recurrenceFunction(id)
}

const startQueue = () => {
    const id:string = uid();
    return recurrenceFunction(id)
}

(async () => {
    return startQueue()
})()

唯一的依赖项是生成唯一键的 uid

当我 运行 它与 ts-node 我可以看到:

所以我们可以看到:

  1. 一旦队列开始。
  2. 只有一个队列。
  3. 它正常工作。

但是当我 运行 通过命令 nexus 使用 nexus 这段代码时 nexus dev 我看到了:

所以:

  1. 两个队列已启动。
  2. 他们同时运行宁。
  3. 他们已经独立创建了变量i

问题:

更新:

我检查过 >= 0.21.1-next.2

的版本是否存在这个问题

0.21.1-next.1应用运行s单次。

重现步骤:

nexus dev
npm i nexus@0.21.1-next.1
nexus dev
npm i nexus@0.21.1-next.2

有引入此行为的提交:

https://github.com/graphql-nexus/nexus/commit/ce1d45359e33af81169b7ebdc7bee6718fe313a8

onMainThreadREFLECTION_ENV_VAR 之类的变量,但没有对文档的引用。我不明白这段代码在做什么?

这可能会在未来记录在这个地方:

https://www.nexusjs.org/#/architecture?id=build-flow

但现在有:

更新 2

我找到了解决方法:

const xid = uid();
let limit=10;
const onApplicationStart = async (cb: () => any):Promise<any> => {
    console.log("can i start?", xid, limit, app.private.state.running);
    if(app.private.state.running) {
        await cb()
        return;
    }
    limit--;
    if(limit <= 0) return ;
    await sleep(100);
    return onApplicationStart(cb);
}

(async () => {

    return onApplicationStart(async () => {
        return startQueue()
    })

})()

但这是暂时的 hack 而不是解决方案。完整示例:

https://github.com/graphql-nexus/nexus/discussions/983

Nexus 不支持依赖副作用的 Eager 模块代码。

参见:

现在的解决方法是像这样包装您的代码:

// app.ts
if (!process.env.NEXUS_REFLECTION) {
  yourHeavyAsyncCode()
}

引用https://github.com/graphql-nexus/nexus/issues/732#issuecomment-626586244