node.js:有一个奇怪的问题,Promse的条件没有被调用

时间:2018-01-29 04:07:42

标签: node.js typescript es6-promise

我正在研究以下Promise场景,并且我不明白为什么第二个然后条件没有在设置方法中受到影响。当这个代码在app.js中运行时,我看到initialize()在哪里被命中,并且它等待按预期进行数据库连接,但是一旦初始化达到了解决条件,就不会出现任何其他被调用的内容。我在catch中设置了断点,但从未调用过;也没有在设置方法中达到的捕获量。我希望在完成后立即调用initializeAppSettings。

我不知道这里有什么问题。我真的需要有人来审查并解释我在这个承诺方案中出错的地方吗?

setup = () => {
    let p = new Promise(initialize)
        .then(this.initializeAppSettings)
        .then(() => {
            this.appServer.listen(3000, () => {
                console.log('Server started on port 3000 :)');
            });
        })
        .catch((err: Error) => {
            throw err;
        });
}

export let initialize = (): Promise<Container> => {
    let p = new Promise((reject, resolve) => {

        var container = new Container();

        initializeDBConnection(process.env.DB_HOST)
            .then((dbClient: Repository.DbClient) => {
                container.bind<DbClient>(TYPES.DbClient).toConstantValue(dbClient);

                resolve(container);
            })
            .catch((err: Error) => {
                reject(err);
            });
        });

        return p;
    }


this.initializeAppSettings = (container: Container): Promise<any> => {
    /*
    * This code is never called
    */
    let p = new Promise((reject, resolve) => {
        let server = new InversifyExpressServer(container);
        server.setConfig((app) => {
            app.use(bodyParser.urlencoded({
                extended: true
            }));
            app.use(bodyParser.json());
            app.use(express.static(path.join(__dirname, "public")));

            //configure pug
            app.set("views", path.join(__dirname, "views"));
            app.set("view engine", "pug");

            //mount logger
            app.use(methodOverride());
        }).setErrorConfig((app) => {
            if (process.env.NODE_ENV === "development") {
                app.use(function (err: Error, req: express.Request, res: express.Response, next: express.NextFunction) {
                    else {
                        //res.status(500).send('An error occurred while processing your request.');
                        res.statusCode = 500;
                        return res.json({
                            errors: ['An error occurred while processing your request.']
                        });
                    }
            }
        });

        this.appServer = server.build();
        resolve();
    });

    return p;
}

1 个答案:

答案 0 :(得分:1)

你在这里创造的外在承诺:

setup = () => {
    let p = new Promise(initialize)
        .then(this.initializeAppSettings)
        .then(() => {
            this.appServer.listen(3000, () => {
                console.log('Server started on port 3000 :)');
            });
        })
        .catch((err: Error) => {
            throw err;
        });
}

永远不会被解析,因此永远不会调用附加到它的.then()处理程序。

这里有很多问题。我不认为我可以覆盖所有这些,但我会通过其中的一些。

首先,您要避免创建新承诺的承诺反模式来包装另一个承诺。你很简单,不需要这样做。因此,如果initialize()是一个函数,它返回一个在它完成时解析的promise(这是代码中的另一个问题,但我们假设它已正确编写),那么你可以这样做:< / p>

setup = () => {
    return initialize()
      .then(this.initializeAppSettings.bind(this))
      .then(() => {
            this.appServer.listen(3000, () => {
            console.log('Server started on port 3000 :)');
        });
    });
}

现在,因为完成this.appServer.listen()没有以任何方式连接到您的承诺链,它会在您需要时启动,但它的完成将无法与您的承诺相协调(只要它想要,它就会完成)。你可以&#34; promisify&#34;它,如果你想将它链接到你的承诺链。

另请注意,我已将this.initializeAppSettings更改为this.initializeAppSettings.bind(this),以便在this处理程序中保留.then()的值。

现在,只有当initialize()返回在适当时间解析的承诺时,上述方法才能正常工作。你确实试图这样做,但是你再一次用诺言反模式来实现它,你就是这样。而不是创建自己的承诺,而应该返回你已经拥有的承诺:

export let initialize = (): Promise<Container> => {
    var container = new Container();
    return initializeDBConnection(process.env.DB_HOST)
        .then((dbClient: Repository.DbClient) => {
                container.bind<DbClient>(TYPES.DbClient).toConstantValue(dbClient);
                // make resolved value be the container
                return container;
    });
}