简体   繁体   English

Node.js MongoDB 利用承诺进行 MongoDB 方法调用

[英]Node.js MongoDB Utilizing promises to make MongoDB method calls

EDIT编辑

So I am creating an e-commerce website and I'm running into a few road blocks.所以我正在创建一个电子商务网站,但遇到了一些障碍。 I have since updated my code to make it cleaner and easier to read and I somewhat pinpointed where my issue stems from (though there could be more).从那以后,我更新了我的代码,使其更清晰、更易于阅读,并且我在一定程度上指出了我的问题的根源(尽管可能还有更多)。 Here is the updated code:这是更新后的代码:

StoreDB.prototype.addOrder = function(order) {
    console.log('addOrder');
    return this.connected.then(function(db) {
        console.log(order);
        var orders = db.collection('orders');
        var products = db.collection('products');
        return insert(order, orders, db)
        .then(function(updatedOrdersList) {
            return obtainOrders(updatedOrdersList);
        })
        .then(function(orderList) {
            return updateProducts(orderList, products);
        })
        .catch((err) => console.log('There was an issue in the promise chain\n' + err));
    });
}

function insert(order, orders, db) {
    return new Promise(function(resolve, reject) {
        console.log('Inserting order into orders collection');
        orders.insert(order);
        resolve(db.collection('orders'));
    });
}

function obtainOrders(orders) {
    return new Promise(function(resolve, reject) {
        console.log('Obtaining orders');
        var orderList = orders.find({}).toArray();
        resolve(orderList);
    });
}

function updateProducts(orderList, products) {
    return new Promise(function(resolve, reject) {
        console.log('Getting the products that match the cart')
        var promises = [];
        var promises2 = [];
        console.log('orderList', orderList);
        for (var item in orderList[0].cart) {
            console.log('item', item);
            promises.push(products.find({$and : [{"_id" : item}, {"quantity" : {$gte: 0}}]}).toArray());
        }
        Promise.all(promises)
            .then(() => {
                console.log('Updating the cart quantity')
                for (var i = 0; i < promises.length; i++) {
                    console.log(promises);
                    // console.log(productList[item], productList[item]._id, productList[item].quantity, cart);
                    promises2.push(products.update({"_id" : productList[item]._id}, {$set :{"quantity" : (productList[item].quantity - cart[productList[item]._id])}}));

                    promises2.push(products.find({}).toArray());
                    Promise.all(promises2)
                        .then(() => promises[promises2.length-1]);                          
                }                       
            }); 
    });
}

It appears that when obtainOrders is called in the promise chain, it returns an empty array.似乎在承诺链中调用obtainOrders时,它返回一个空数组。 I'm not too sure why it does this because in the chain where:我不太确定为什么要这样做,因为在链中:

return insert(order, orders, db)
.then(function(updatedOrdersList) {
    return obtainOrders(updatedOrdersList);
})
.then(function(orderList) {
    return updateProducts(orderList, products);
})

The function call to obtainOrders from above waits for the method call to Collections.find to be completed before it is resolved (returning an array of orders).上面对obtainOrders的函数调用等待对 Collections.find 的方法调用完成,然后再解析(返回订单数组)。 Some reason it is returning an empty array.它返回一个空数组的某种原因。

Any help would be greatly appreciated!任何帮助将不胜感激!

Not sure what the relationship between the first block and second is, but in the first block:不确定第一个块和第二个块之间的关系是什么,但在第一个块中:

function insert(order, orders, db) {
    return new Promise(function(resolve, reject) {
        console.log('Inserting order into orders collection');
        orders.insert(order);
        resolve(db.collection('orders'));
    });
}

At a glance it seems like orders.insert(order) is asynchronous, but you're not waiting for it to finish before resolving.乍一看,好像orders.insert(order)是异步的,但您并不是在等待它完成后再解析。

You could either make the function asynchronous and您可以使函数异步和

await orders.insert(order);

or要么

orders.insert(order)
  .then(() => resolve(db.collection('orders')))

But doesn't having the method Collections.insert inside a promise make that method call asynchronous?但是,在 promise 中使用方法 Collections.insert 不会使该方法调用异步吗?

Yes, Collections.insert is implicitly asynchronous in that it returns a Promise.是的, Collections.insert是隐式异步的,因为它返回一个 Promise。 I was talking about declaring it async explicitly so you can await other async calls in the function body.我说的是显式声明它是async的,这样你就可以await函数体中的其他异步调用。 Note the addition of async at the start and await orders.insert() .请注意在开始时添加了asyncawait orders.insert()

async function insert(order, orders, db) {
    return new Promise(function(resolve, reject) {
        console.log('Inserting order into orders collection');
        await orders.insert(order);
        resolve(db.collection('orders'));
    });
}

If you don't await orders.insert (either via await or .then ) you're calling insert and immediately returning the db.collection call, which creates a race condition where the new order may not be inserted yet.如果您不 await orders.insert (通过await.then ),您将调用insert立即返回db.collection调用,这会创建一个竞争条件,新订单可能尚未插入。 It's possible the new order could be there but it seems unlikely, and it's not going to be there reliably.新订单可能存在,但似乎不太可能,而且不会可靠地存在。

There's also no need to create a new Promise here.也无需在此处创建新的 Promise。 db.collection already returns a Promise. db.collection已经返回一个 Promise。 Just return the one you already have:只需返回您已有的那个:

function insert(order, orders, db) {
    console.log('Inserting order into orders collection');
    return orders.insert(order)
        .then(() => db.collection('orders'));
}

Take a look at this sample code snippet.看看这个示例代码片段。 I've mocked out the orders.insert and db.collection methods.我模拟了orders.insertdb.collection方法。

 // mock orders.insert const orders = { insert: async() => { return new Promise((resolve) => { // wait a second then resolve setTimeout(resolve, 1000); }); } } // mock db.collection const db = { collection: async() => { return new Promise((resolve) => { // wait a second then resolve with mock data setTimeout(() => resolve(['foo', 'bar', 'baz']), 1000); }); } } function insert(order, orders, db) { return orders.insert(order).then(() => db.collection('orders')); } // same as above, but with async/await async function insertAsync(order, orders, db) { await orders.insert(order); return await db.collection('orders'); } function go() { // using then insert(null, orders, db).then(console.log); // using async/await; insertAsync(null, orders, db).then(console.log); } go();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM