繁体   English   中英

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

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

编辑

所以我正在创建一个电子商务网站,但遇到了一些障碍。 从那以后,我更新了我的代码,使其更清晰、更易于阅读,并且我在一定程度上指出了我的问题的根源(尽管可能还有更多)。 这是更新后的代码:

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]);                          
                }                       
            }); 
    });
}

似乎在承诺链中调用obtainOrders时,它返回一个空数组。 我不太确定为什么要这样做,因为在链中:

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

上面对obtainOrders的函数调用等待对 Collections.find 的方法调用完成,然后再解析(返回订单数组)。 它返回一个空数组的某种原因。

任何帮助将不胜感激!

不确定第一个块和第二个块之间的关系是什么,但在第一个块中:

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'));
    });
}

乍一看,好像orders.insert(order)是异步的,但您并不是在等待它完成后再解析。

您可以使函数异步和

await orders.insert(order);

要么

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

但是,在 promise 中使用方法 Collections.insert 不会使该方法调用异步吗?

是的, Collections.insert是隐式异步的,因为它返回一个 Promise。 我说的是显式声明它是async的,这样你就可以await函数体中的其他异步调用。 请注意在开始时添加了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'));
    });
}

如果您不 await orders.insert (通过await.then ),您将调用insert立即返回db.collection调用,这会创建一个竞争条件,新订单可能尚未插入。 新订单可能存在,但似乎不太可能,而且不会可靠地存在。

也无需在此处创建新的 Promise。 db.collection已经返回一个 Promise。 只需返回您已有的那个:

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

看看这个示例代码片段。 我模拟了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