【问题标题】:Sails Waterline ORM query inside array.map()在 array.map() 中的 Sails Waterline ORM 查询
【发布时间】:2017-11-10 04:51:54
【问题描述】:

下面的代码 sn-p 使用sails waterline ORM 进行数据库查询和发送响应。但是,执行流程很奇怪,map函数之外的代码在map函数执行完成之前就已经运行了。在“我在地图内”之前,“我在地图外”正在控制台中打印。我认为可以使用 Promise 或 async / await 来解决这个问题。我试过在下面使用 Promise.all() ,但它不起作用,响应总是一个空数组。如果您能举例说明如何解决此类问题,我将不胜感激。

allMembers: (req, res) => {
  const projectId = req.params.id;

    ProjectMembers.find({projectId: projectId}).exec( (err, members) => {
        if(err) res.serverError("bad request!");

        if(members.length === 0) res.notFound({message: "No members are found for this project!"});

        let membersInfo = [];
        let promise = Promise.all(members.map(m => {
            User.findOne({id: m.userId}).exec( (err, user) => {
                if(err) membersInfo.push({name: null, userId: null, email:null,rate:null, error: 'Internal error!'})
                else if(!user) membersInfo.push({name: null, userId: null, email:null,rate:null, error: 'No user found'})
                else membersInfo.push({name: user.name, userId: user.id, rate: m.rate, error: null})
                console.log("i am inside of map");
            })
        }));

    console.log("I am outsie of map")
    promise.then( (resolve) => {return res.ok({members: membersInfo})});
}

【问题讨论】:

    标签: javascript async-await sails.js es6-promise waterline


    【解决方案1】:

    我正要告诉你“不要在.map 中使用查询”,但仔细一看,我认为你的代码非常接近工作。 Promise.all 的参数必须是一组承诺。每个User.findOne 确实是一个promise - 绊脚石是一旦你使用.exec 它就不再返回promise。

    我认为答案是在.then 内部进行处理,而不是在.map 内部进行处理:

    ProjectMembers.find({projectId: projectId}).exec( (err, members) => {
        if(err) return res.serverError("bad request!");
    
        if(members.length === 0) return res.notFound({message: "No members are found for this project!"});
    
        let promise = Promise.all(members.map(m => User.findOne({id: m.userId})));
    
        promise.then( (values) => {
            // values is the array of user objects returned from the array of queries
            let membersInfo = values.map((user) => {
                if (!user) {
                    return {name: null, userId: null, email:null,rate:null, error: 'No user found'};
                } else {
                    return {name: user.name, userId: user.id, rate: m.rate, error: null};
                }
            });
            return res.ok({members: membersInfo});
        }, (err) => {
            return res.serverError("Error finding users");
        });
    

    Promise 只有一个失败回调,因此您无法单独捕获和处理查询错误(尽管您仍然可以单独处理未找到的结果)。

    【讨论】:

    • 好。根据您选择的数据库,您可以在用户 ID 上使用 OR 标准而不是单个的 fonOne 来做一个大的User.find
    • @ManuelReil 这就是我会采取的方法,并且 waterline 绝对可以用任何底层数据库做到这一点。我只是试图保持接近 OP 的合理且接近工作的逻辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-18
    • 2020-07-20
    • 1970-01-01
    • 2014-01-01
    • 2013-12-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多