簡體   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