嵌套的异步javascript函数

时间:2016-03-08 08:47:32

标签: javascript asynchronous sails.js

我正在使用waterline + sails作为一个api,我有以下函数嵌套exec()调用。

AcademyService.getAll().exec(function (error, data) {

        if (error) {

            return res.json({result: false, message: error});

        }

        var academies = data;

        for (var i = 0; i < Object.keys(academies).length; i++) {

            var user_id;

            user_id = academies[i].academy_user_id;

            (function (index) {

                UserService.getOneById(user_id).exec(function (error, data) {

                    if (error) {

                        academies[index].academy_user_id = null;

                    }

                    academies[index].academy_user_id = data.user_fname+" "+data.user_lname;

                });

            })(i);

        }

        return res.json({result: true, academies: academies});

    });

上面代码的问题在于,最后一个return语句没有更新的academies对象。即它没有academy_user_id的更新值。我将此归因于调用的异步行为,我认为当我们到达最后一个返回时,UserService的异步调用仍在循环中运行,并且未传递更新的academies对象。< / p>

现在,一个仓促的解决方案是使用循环结束检查从academies回调中返回UserService.getOneById对象,但这似乎不是正确的方法。那么,我们能以某种方式同步地进行内部exec()吗?

1 个答案:

答案 0 :(得分:1)

Sails捆绑了async库,非常适合这种情况。 Async在sails中全局可用,因此您不需要它,甚至可以将其添加到依赖项中。

使用async.each代替你的for循环。

这样的事情应该有效

AcademyService.getAll().exec(function(error, academies) {
    if (error) {
        return res.json({
            result: false,
            message: error
        });
    }

    async.each(
        academies,
        function (academy, cb) {
            var user_id = academy.user_id;

            UserService.getOneById(user_id).exec(function (err, user) {
                if (err) {
                    academy.academy_user_id = null;
                }
                else {
                    academy.academy_user_id = user.user_fname + ' ' + user.user_lname;
                }

                return cb();
            });
        },
        function (err) {
            if (err) {
                return res.json({
                    result: false,
                    message: err
                });
            }

            return res.json({
                result: true,
                academies: academies
            });
        }
    );
});