Async Mongoose callbacks in then statement

2019-03-05 04:04发布

问题:

I have the issue with using promises and async calls from Mongoose

Here is my code

 req.checkBody(BookManager.SCHEME);
        req.getValidationResult()
            .then(function (result) {
                if (!result.isEmpty()) {
                    handler.onError('Invalid payload');
                    return;
                }
                return new BookModel({
                    author: data.author,
                    name: data.name,
                    year: data.year
                });
            })
           .then((book) => {
            BookModel.find({name: book.name}, function (err, docs) {
                if (docs.length) {
                    throw new Error("Book already exists");
                } else {
                    return book;
                }
            });
            })
            .then((book) => {
                book.save();
            })
            .then((saved) => {
                handler.onSuccess(saved);
            })
            .catch((error) => {
                handler.onError(error.message);
            });

As you can see from the code above. I am checking whether such book already exists and in order to do this I use async find method that is called after the main "program counter" has gone further.

How can I solve this problem ?

Also please tell me whether I have chosen the right wait to implement my use case ? Maybe I am doing it wrong and there are some other best practices to handle this.

回答1:

I believe your second then(..) should look more like this:

.then(function(book){
    return new Promise(function(resolve, reject){
        BookModel.find({ name: book.name }, function(err, docs) {
            if (docs.length) {
                reject({message: "Book already exists"});
            } else {
                resolve(book);
            }
        });
    });
})


回答2:

You must not pass a callback to BookModel.find() to get back a promise. Also you must not forget to return the promises from your then callbacks to continue chaining:

req.getValidationResult().then(result => {
    if (!result.isEmpty()) {
        throw 'Invalid payload';
    }
    return new BookModel({
        author: data.author,
        name: data.name,
        year: data.year
    });
}).then(book =>
    BookModel.find({name: book.name}).then(docs =>
        book
    , err => {
        throw new Error("Book already exists");
    })
).then(book =>
    book.save()
).then(handler.onSuccess, handler.onError);

Also I fixed your problem with the invalid payload.