亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 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 關注
  • 178 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號