搜索

首页  >  问答  >  正文

javascript - node异步问题

想要callback在findById之后执行,但又不能放在它的回调中,不然会执行多次。应该怎么办?

大家讲道理大家讲道理2842 天前380

全部回复(6)我来回复

  • 漂亮男人

    漂亮男人2017-05-16 13:25:54

    软件是服务行业,要有服务意识……代码贴图没问题,可以看得很清晰,但是如果回答者想改你的代码,还得重新敲一遍…………

    我看你已经用了 es6 的语法,所以正解肯定是 Promise,可以自己封装成 Promies

    exports.findList = function(findObj, callback) {
        Info.find(findObj, function(err, info) {
            const promises = info.map(f => new Promise((resolve, reject) => {
                f.image = f.images.split(",")[0];
                User.findById(f.author_id, function(error, user) {
                    if (error) {
                        reject(error);
                        return;
                    }
    
                    f.author_name = user.name;
                    f.authro_avatar = user.avatar;
                    resolve(f);
                });
            }));
    
            Promise.all(promises)
                .then(function(values) {
                    // 成功的时候,这个 values 是所有 info 对象,
                    // 作为一个数组返回出来,而不是某一个
                    callback(null, values);
                })
                .catch(function(error) {
                    // 注意这里 error 是第一个失败 error
                    // 不是所有的 error 
                    callback(error);
                });
        });
    };

    当然也可以用 Bluebird 提供的工具函数来封装 Promise

    需要注意的是你这里运行了好多个异步调用,所以要一起返回的话,肯定也是好多个结果。所以注意 Promise.all 后面 then() 中的回调。

    如果你要用 es5,建议你写成 es6 再 Babel。不过 Node 7.6+ 已经支持 es2017 的一些特性,所以其实不必在意这个问题。如果确实需要,就采用在 findById 回调中记数的办法,记满放大招(调用 callback)。

    回复
    0
  • 我想大声告诉你

    我想大声告诉你2017-05-16 13:25:54

    方案一

    使用 async/await。这样就可以按照同步方式使用 User.findById

    方案二

    在循环中把 User.findById 加入一个数组,然后用 Promise.allcallback 写在 Promise.all().then() 中。

    方案三

    使用一个状态变量,每次检查一下,满足条件再执行 callback。丑陋的方法,不要用。

    回复
    0
  • 天蓬老师

    天蓬老师2017-05-16 13:25:54

    设置个参数,执行完设置下,以后每次进入回调判断下 ..

    回复
    0
  • 某草草

    某草草2017-05-16 13:25:54

    对于callback地狱,请使用Promise 或者类似类库。

    回复
    0
  • 巴扎黑

    巴扎黑2017-05-16 13:25:54

    exports.findList=function (findObj,callback) {
        Info.find(findObj,function (err,info) {
            for(let i in info){
                info[i].image=info[i].images.split(',')[0];
                User.findById(info[i].author_id,function (error,user) {
                    info[i].author_name=user.name;
                    info[i].author_avatar=user.avatar;
                    if(i==info.length-1){
                        callback(err,info);
                    }
                })
            }
        })
    }

    我的解决方法,有点low。。?

    回复
    0
  • 迷茫

    迷茫2017-05-16 13:25:54

    二楼说得对,用promise解决。

    回复
    0
  • 取消回复