使用Mongoose处理嵌套回调/承诺

时间:2017-07-26 03:08:56

标签: callback promise

我是Node.js和Mongoose的初学者。我花了一整天的时间试图通过SO搜索解决问题,但我找不到合适的解决方案。基本上,我使用一个集合中检索到的值来查询另一个集合。为了做到这一点,我正在迭代先前检索结果的循环。

通过迭代,我可以填充我需要的结果。不幸的是,我遇到问题的地方是在数组中收集所需信息之前发回的响应。我知道这可以通过回调/承诺来处理。我尝试了很多方法,但我的尝试并没有成功。我现在正试图利用Q library来促进回调。我真的很感激一些见解。这是我目前陷入困境的部分片段:

var length = Object.keys(purchasesArray).length;
var jsonArray = [];

var getProductDetails = function () {
var deferred = Q.defer();
for (var i = 0; i < length; i++) {
    var property = Object.keys(purchasesArray)[i];
    if (purchasesArray.hasOwnProperty(property)) {
        var productID = property;
        var productQuery = Product.find({asin: 
        productQuery.exec(function (err, productList) {
        jsonArray.push({"productName": productList[0].productName,
                           "quantity": purchasesArray[productID]});
        });
    }
}

return deferred.promise;
};

getProductDetails().then(function sendResponse() {
    console.log(jsonArray);
    response = {
        "message": "The action was successful",
        "products": jsonArray
    };
    res.send(response);
    return;
 }).fail(function (err) {
     console.log(err);
    })
 });

我特别能够在jsonArray数组中发送两个对象中的一个,因为响应是在第一个元素之后发送的。

更新

感谢 Roamer-1888 的回答,我已经能够构建一个有效的JSON响应,而不必担心在发送响应后设置标头的错误。

基本上,在getProductDetails()函数中,我尝试从映射purchasesArray中每个项目的数量时从Mongoose查询中检索产品名称。从函数中,最终,我想形成以下响应:

 response = {
     "message": "The action was successful",
     "products": jsonArray
 };

其中,jsonArray的格式如下getProductDetails

jsonArray.push({
    "productName": products[index].productName,
    "quantity": purchasesArray[productID]
});

1 个答案:

答案 0 :(得分:1)

假设purchasesArray是先前查询的结果,您似乎正在尝试:

  • purchasesArray项目
  • 查询您的数据库一次
  • 形成一个对象数组,每个对象包含从查询和原始purchasesArray项中派生的数据。

如果是这样,并且几乎没有其他猜测,那么以下模式应该可以胜任:

var getProductDetails = function() {
    // map purchasesArray to an array of promises
    var promises = purchasesArray.map(function(item) {
        return Product.findOne({
            asin: item.productID // some property of the desired item
        }).exec()
        .then(function product {
            // Here you can freely compose an object comprising data from :
            // * the synchronously derived `item` (an element of 'purchasesArray`)
            // * the asynchronously derived `product` (from database).
            // `item` is still available thanks to "closure".
            // For example :
            return {
                'productName': product.name,
                'quantity': item.quantity,
                'unitPrice': product.unitPrice
            };
        })
        // Here, by catching, no individual error will cause the whole response to fail.
        .then(null, (err) => null); 
    });
    return Promise.all(promises); // return a promise that settles when all `promises` are fulfilled or any one of them fails.
};

getProductDetails().then(results => {
    console.log(results); // `results` is an array of the objects composed in getProductDetails(), with properties  'productName', 'quantity' etc.
    res.json({
        'message': "The action was successful",
        'products': results
    });
}).catch(err => {
    console.log(err);
    res.sendStatus(500); // or similar
});

您的最终代码将在细节上有所不同,特别是在组合对象的构成方面。不要依赖我的猜测。

相关问题