为了账号安全,请及时绑定邮箱和手机立即绑定

在 Node.js 中为 mongoDB 链接多个承诺函数

在 Node.js 中为 mongoDB 链接多个承诺函数

LEATH 2021-08-20 16:12:23
有一个要求,只有在找到产品和用户时才能添加评论。所以我编写了代码来实现这个场景。User.findById(req.params.userId).exec()        .then(response => {            console.log("response", response);            if (response) {                return Product.findById(req.params.productId).exec();            }            else {                return res.status(404).json({                    message: 'User not found'                })            }        })        .then(response => {            console.log("response", response);            if (!response) {                return res.status(404).json({                    message: 'Product not found'                })            }            const review = new Review({                _id: mongoose.Types.ObjectId(),                rev: req.body.rev,                productId: req.params.productId,                userId: req.params.userId            });            return review.save();        })        .then(response => {            console.log("responseeeeeeee", response);            res.status(201).json({                response            })        })        .catch(error => {            console.log("error", error);            res.status(500).json({                error            })        })这工作正常,但一旦产品或用户丢失,它就会发出警告:(node:17276) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client    at ServerResponse.setHeader (_http_outgoing.js:470:11)    at ServerResponse.header (D:\backup-learning\project-shop-always\node_modules\express\lib\response.js:771:10)    at ServerResponse.send (D:\backup-learning\project-shop-always\node_modules\express\lib\response.js:170:12)    at ServerResponse.json (D:\backup-learning\project-shop-always\node_modules\express\lib\response.js:267:15)    at User.findById.exec.then.then.then.catch.error (D:\backup-learning\project-shop-always\api\controllers\review-controller.js:58:29)    at process._tickCallback (internal/process/next_tick.js:68:7)
查看完整描述

1 回答

?
浮云间

TA贡献1829条经验 获得超4个赞

问题在于,res.status当您return res.status(/*...*/)从then回调中执行操作时,该链会继续使用作为履行值的返回值。


您不能为此使用单个链。此外,由于您需要同时定位用户和产品,因此最好并行执行该操作。见评论:


// *** Start both the product and user search in parallel

Promise.all([

    User.findById(req.params.userId).exec(),

    Product.findById(req.params.productId).exec()

])

.then(([user, product]) => {

    // *** Handle it if either isn't found

    if (!user) {

        res.status(404).json({

            message: 'User not found'

        });

    } else if (!product) {

        res.status(404).json({

            message: 'Product not found'

        });

    } else {

        // *** Both found, do the review

        const review = new Review({

            _id: mongoose.Types.ObjectId(),

            rev: req.body.rev,

            productId: req.params.productId,

            userId: req.params.userId

        });

        // *** Return the result of the save operation

        return review.save()

        .then(response => {

            console.log("responseeeeeeee", response);

            res.status(201).json({

                response

            });

        }

    }

    // *** Implicit return of `undefined` here fulfills the promise with `undefined`, which is fine

})

.catch(error => {

    // *** An error occurred finding the user, the product, or saving the review

    console.log("error", error);

    res.status(500).json({

        error

    })

});

如果您在任何现代版本的 Node.js 中执行此操作,您可以使用async函数和await:


// *** In an `async` function

try {

    const [user, product] = await Promise.all([

        User.findById(req.params.userId).exec(),

        Product.findById(req.params.productId).exec()

    ]);

    if (!user) {

        res.status(404).json({

            message: 'User not found'

        });

    } else if (!product) {

        res.status(404).json({

            message: 'Product not found'

        });

    } else {

        // *** Both found, do the review

        const review = new Review({

            _id: mongoose.Types.ObjectId(),

            rev: req.body.rev,

            productId: req.params.productId,

            userId: req.params.userId

        });

        const response = await review.save();

        console.log("responseeeeeeee", response);

        res.status(201).json({

            response

        });

    }

} catch (error) {

    console.log("error", error);

    res.status(500).json({

        error

    })

}

请注意,整个代码包装在一个try/ catch,所以async功能这是永远都不会拒绝(除非console.log或res.send在catch块中引发错误),这样就不会导致未处理拒绝警告,如果你只是让你Express端点处理程序async(而通常将async函数传递给不希望收到承诺的东西是一种反模式)。(如果您想有点偏执,请将catch块的内容包装在另一个try/ 中catch。)


查看完整回答
反对 回复 2021-08-20
  • 1 回答
  • 0 关注
  • 144 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信