【问题标题】:Handling nested callbacks/promises with Mongoose使用 Mongoose 处理嵌套的回调/承诺
【发布时间】:2017-07-27 13:45:54
【问题描述】:

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

通过迭代,我能够填充我需要的结果。不幸的是,我遇到问题的领域是在数组中收集所需信息之前将响应发送回。我知道这可以通过回调/承诺来处理。我尝试了很多方法,但我的尝试并没有成功。我现在正在尝试使用Q library 来促进回调。我真的很感激一些见解。这是我目前卡住的部分的 sn-p:

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() 函数中,我试图从Mongoose 查询中检索产品名称,同时映射purchasesArray 中每个项目的数量。从函数来看,最终我想形成以下响应:

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

其中,jsonArray 将采用来自getProductDetails 的以下形式:

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

【问题讨论】:

  • 您说“我正在使用从一个集合中检索到的值来查询另一个”,但代码仅包含数组 purchasesArray 中的每个项目的一个查询。那么它是一个查询还是两个查询?
  • 或者,换一种说法,purchasesArray 是不是代码中没有显示的查询结果?
  • @Roamer-18888,感谢您调查我的问题。你的猜测是对的。 purchasesArray 确实是前面查询的结果。我删除了之前的查询以避免混淆。
  • 所以,我的答案很接近。不要担心告诉它是否在数英里之外,我会删除它。
  • 您的回答对我发送 JSON 响应有很大帮助。请查看我更新的帖子以了解我的一些最终查询。

标签: callback promise


【解决方案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
});

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

【讨论】:

  • @Roamer-18888,非常感谢您的有用回答。在您提到我可以从“项目”和“产品”组成一个对象的部分中,我正在尝试填充 jsonArray(类似于我在更新中提到的表单)。我尝试将元素推送到数组上,但后来意识到这必须是一个对象。当我尝试组合具有适当属性的对象时,由于“需要换行符或分号”的警告,我无法这样做。如果我的查询相当愚蠢,我很抱歉。我是 Node.js 的新手,并承诺使用 JavaScript。
  • 感谢您阐明results 的用法。我知道results 本质上等同于jsonArray 的使用。请帮助我解决对象的构成。您已经用productNamequantityunitPrice 等属性说明了一个示例。我注意到我的编辑器中有一个警告,不允许我传递属性。我收到错误 expecting newline or semicolon 。我无法按照您为productName : product.productNamequantity : jsonArray[item] 描述的方式编写它
  • 我意识到 jsonArray 应该被重命名为别的东西。我已经了解results 的用法。目前,您的代码示例包含来自同步和异步派生成员的数据,我无法在回调中组合对象。
  • 好的,抱歉,我现在明白了。语法错误是我造成的。我会编辑。
  • 删除上面的评论。我试图告诉你一些你已经知道的事情。
猜你喜欢
  • 2017-10-13
  • 1970-01-01
  • 2020-12-15
  • 1970-01-01
  • 2019-02-24
  • 2020-03-29
  • 2018-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多