Mongoose/Typescript - UnhandledPromiseRejectionWar

2019-08-22 06:14发布

问题:

I'm not sure why I'm seeing this UnhandledPromiseRejectionWarning. In this code, 'id' is a Mongoose Index, and I am testing inserting a duplicate ID which should be handled properly.

router.post('/create/:id', jsonParser, (req: Request, res: Response) => {
    let { id } = req.params;
    if (!req.body) {
        return res.sendStatus(400)
    }

    // @TODO add validation on JSON
    let promise = Requirement.create({id: id, data: req.body.data, deleted: false});

    promise.then((requirement) => {
        return res.json(requirement);
    });

    promise.catch((reason) => {
        let err = {'error': reason};
        return res.json(err);
    });
});

In fact, the following JSON is returned, so I know my rejection handler is executing:

{
    "error": {
        "name": "MongoError",
        "message": "E11000 duplicate key error collection: rex.requirements index: id_1 dup key: { : \"REQ001\" }",
        "driver": true,
        "index": 0,
        "code": 11000,
        "errmsg": "E11000 duplicate key error collection: rex.requirements index: id_1 dup key: { : \"REQ001\" }"
    }
}

The exact warnings I'm seeing are the following:

(node:11408) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): MongoError: E11000 duplicate key error collection: rex.requirements index: id_1 dup key: { : "REQ001" }
(node:11408) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

回答1:

catch catches an error from promise but not promise.then(...). If an error is thrown inside then, this would result in unhandled rejection. Even if it's not thrown but is propagated from promise, it is considered uncaught in this promise.

It should be:

promise
.then((requirement) => {
    return res.json(requirement);
})
.catch((reason) => {
    let err = {'error': reason};
    return res.json(err);
});


回答2:

You basically did

var a = promise.then(…);
var b = promise.catch(…);

creating a branch in the chain. If promise is getting rejected now, the catch callback will be called and b will be a fulfilled promise just fine, but the a promise is getting rejected too and nobody handles that.

Instead, you should use both arguments of then and write

Requirement.create({id: id, data: req.body.data, deleted: false})
.then(requirement => {
    res.json(requirement);
}, reason => {
    let err = {'error': reason};
    res.json(err);
});