等待forEach的结果,然后将回调发送至main

时间:2019-03-15 07:06:11

标签: node.js express mongoose promise

我想与其子项(与该产品ID绑定的另一项)一起收集数据 我有一个采用这种模式的收藏

// User Schema
const filtersSchema = mongoose.Schema({
    filter_name:{
        type: String,
        required: true
    },
    filter_code:{
        type: String,
        required: true,
        unique: true
    },
    bind_to: {
        type: Schema.Types.ObjectId,
        default: null
    },
    filter_status:{
        type: Boolean,
        default: true
    },
    created_on:{
        type: Date,
        default: Date.now
    },
    updated_on:{
        type: Date,
        default: Date.now
    }
});

如果我向其输入数据,则默认的bind_to值为null,表示其父级。如果我发送父母的bind_to ID,它将是ObjectID。

我想收集这样的数据

[{
-- parent object --
children:[
  {
  -- child object --
  },
  {
  -- child object --
  }
]
}]

如果我们有多个项目,它将通过循环(forEach),但是在forEach循环完成之前将发送回调。我知道forEach是异步的,请求是同步的。但是对如何做到这一点感到困惑!

您可以在下面看到模块

// Get Filters by Parent ID
module.exports.getFiltersByParentId = (pid, callback) => {
    Filters.find({bind_to: pid}, callback);
}

//For getting the parent object and looping it to get its child objects
module.exports.getFilters = (callback, limit) => {
    Filters.find({bind_to: null}, (err, filters) => {
        if (err) {
            console.log(err);
            let obj = {status: false, error: err.errmsg};
            callback(obj);
        } else {
            const resObj = [];
            filters.forEach(async function (ele) {
                await Filters.getFiltersByParentId(ele._id, (err, cfil) => {
                    if (err) {
                        let obj = {status: false, message: err.errmsg};
                        callback(obj);
                    } else {
                        console.log(ele, "Obj");
                        ele.children = cfil;
                        resObj.push(ele);
                    }
                });
            });
            Promise.all(resObj).then(res => {
                let obj = {status: true, data: res, message: "Filters found"};
                callback(obj);
            });
        }
    });
}

,但在这种情况下,结果对象将为空。如何获得具有上述值的正确对象?

即使我尝试了这种方法

const resObj = [];
            filters.map(function (ele) {
                Filters.getFiltersByParentId(ele._id, (err, cfil) => {
                    if (err) {
                        let obj = {status: false, message: err.errmsg};
                        callback(obj);
                    } else {
                        console.log(ele, "Obj");
                        ele.children = cfil;
                        resObj.push(ele);
                    }
                });
            });
            Promise.all(resObj).then(res => {
                let obj = {status: true, data: res, message: "Filters found"};
                callback(obj);
            });

还有这个

Promise.all(filters.map(function (ele) {
                Filters.getFiltersByParentId(ele._id, (err, cfil) => {
                    if (err) {
                        let obj = {status: false, message: err.errmsg};
                        callback(obj);
                    } else {
                        console.log(ele, "Obj");
                        ele.children = cfil;
                        resObj.push(ele);
                    }
                });
            })).then(res => {
                let obj = {status: true, data: res, message: "Filters found"};
                callback(obj);
            });

好的,现在我从getFiltersByParentId

返回了一个承诺
module.exports.getFiltersByParentId = (pid, callback) => {
    return new Promise(function(resolve, reject) {
        Filters.find({bind_to: pid}, function (err, results) {
            if (err) {
                reject(err);
            } else {
                resolve(results);
            }
        })
    });
}

2 个答案:

答案 0 :(得分:1)

首先,由于Filters.getFiltersByParentId不返回承诺,因此await做出回应毫无意义-因此,我将其包装在新的Promise中-如果有时间,可能会更简单无需担心async / await的方法,因为除了没有引入使用async / await的诺言外,代码中实际上没有任何诺言

仍然,我认为代码更容易阅读,因此,让我们保持异步/等待和承诺主题

第二,使用for ... of循环使代码非常简单,特别是因为您希望任何错误都可以停止对Filters.getFiltersByParentId的进一步调用

代码如下

module.exports.getFilters = (callback, limit) => {

    Filters.find({bind_to: null}, async (err, filters) => {
        if (err) {
            console.log(err);
            let obj = {status: false, error: err.errmsg};
            callback(obj);
        } else {
            const resObj = [];
            for (const ele of filters) {
                try {
                    let result = await new Promise((resolve, reject) => {
                        Filters.getFiltersByParentId(ele._id, (err, cfil) => {
                            if (err) {
                                let obj = {status: false, message: err.errmsg};
                                reject(obj);
                            } else {
                                console.log(ele, "Obj");
                                ele.children = cfil;
                                resolve(ele);
                            }
                        });
                    });
                    resObj.push(result);
                } catch(e) {
                    return callback(obj);
                }
            }
            let obj = {status: true, data: resObj, message: "Filters found"};
            callback(obj);
        }
    });
};

编辑:我有时间:p

这是没有异步/等待的代码,因为没有承诺

module.exports.getFilters = (callback, limit) => {
    Filters.find({bind_to: null}, (err, filters) => {
        if (err) {
            console.log(err);
            let obj = {status: false, error: err.errmsg};
            callback(obj);
        } else {
            const resObj = [];
            const getFilters = (index) => {
                if (index < filters.length) {
                    const ele = filters[index];
                    Filters.getFiltersByParentId(ele._id, (err, cfil) => {
                        if (err) {
                            let obj = {status: false, message: err.errmsg};
                            callback(obj);
                            return;
                        } else {
                            console.log(ele, "Obj");
                            ele.children = cfil;
                            getFilters(index + 1);
                        }
                    });
                } else {
                    let obj = {status: true, data: resObj, message: "Filters found"};
                    callback(obj);
                }
            };
            getFilters(0);
        }
    });
};

答案 1 :(得分:0)

对问题进行了一些更改并使用@Jaromanda X's@CertainPerformance指南后,我想出了一个解决问题的方法。它不完全符合我的要求,但输出却完全相同。

我将g Filters.getFiltersByParentId方法更改为返回Promise

module.exports.getFiltersByParentId = (pid, callback) => {
    return new Promise(function(resolve, reject) {
        Filters.find({bind_to: pid._id}, function (err, results) {
            if (err) {
                reject(err);
            } else {
                let obj = {parent: pid, children: results};
                resolve(obj);
            }
        })
    });
}

然后将forEach更改为array.map,并在Promise.all函数中使用了promise数组

module.exports.getFilters = (callback, limit) => {
    Filters.find({bind_to: null}, (err, filters) => {
        if (err) {
            console.log(err);
            let obj = {status: false, error: err.errmsg};
            callback(obj);
        } else {
            const resObj = [];
            var promises = [];

            filters.map(function (ele) {
                promises.push(Filters.getFiltersByParentId(ele, (err, cfil) => {
                    if (err) {
                        let obj = {status: false, message: err.errmsg};
                        callback(obj);
                    } else {
                        console.log(ele, "Obj");
                        ele.children = cfil;
                        resObj.push(ele);
                    }
                }));
            });

            Promise.all(promises).then(res => {
                let obj = {status: true, data: res, message: "Filters found"};
                callback(obj);
            });

        }
    });
}

最后,我的输出看起来像这样

[
 {
  parent: {
   --- parent object ---
  },
  children: [
    {
     --- child object 1 ---
    },
    {
     --- child object 2 ---
    },
    {
     --- child object n ---
    }
  ]
 }
]