【问题标题】:How To Use Variables Down A Promise Chain如何在 Promise 链中使用变量
【发布时间】:2016-01-31 10:47:23
【问题描述】:

我正在使用带有 express 框架的 nodejs 和 mongodb/mongoose 来存储我的数据。

我有一个注册函数,它可以做 4 件事。创建用户,创建令牌,将令牌分配给用户,最后发送电子邮件。

我最初使用效果很好的回调来做到这一点。我现在尝试使用承诺,我需要蓝鸟来做到这一点。但是,当一个承诺完成时,我需要在下一个承诺中使用返回的变量。

注册函数

module.exports.register = function(req, res) {

    var input = req.body;

    var newUser = new User ({

        username: input.username,
        email: input.email,
        password: input.password,
        active: false

    });

    var promise = newUser.save();

    promise.then(function(user) {

        return createToken('new', null, user._id);

    }).then(function(token) {

        user.tokens.push(token._id);

        return user.save();

    }).then(function(user) {

        //Do Email Stuff

    }).catch(function(err) {

        return res.json("Could Not Register");

    });
}

创建令牌函数

var createToken = function(type, expiry, userid) {

    var token = uuid.v4();

    return new Promise(function(resolve, reject) {

        var newToken = Token({

            type:type,
            token: token,
            expiry: expiry,
            user: userid

        });

        var promise = newToken.save();

        promise.then(function(token) {

            resolve(token);

        }).catch(function(err) {

            reject(err);

        });

    });

};

所以我在做“user.tokens.push”的地方找不到用户。我在蓝鸟中读到我可以使用称为绑定的东西?然后使用“这个”。谁能告诉我如何正确地做到这一点。

此外,如果每个承诺中都有错误,我希望 catch 方法是动态的。而不仅仅是“无法注册”,而是“无法保存用户”或“无法保存令牌”,具体取决于哪个承诺失败。

如果有办法让这更干净,请告诉我。

【问题讨论】:

  • 您正在引用 user.tokens.push 但您的代码示例中没有用户变量。也许示例不完整或者您忘记检索用户?
  • @shershen - 我想你已经确定了问题的重点

标签: javascript node.js mongodb express


【解决方案1】:

在 register 函数范围内使用 var 来存储 user 的值以供以后使用并不可耻

module.exports.register = function(req, res) {
    var input = req.body;
    var newUser = new User ({
        username: input.username,
        email: input.email,
        password: input.password,
        active: false
    });
    var sUser; // store user in this var
    newUser.save()
    .then(function(user) {
        sUser = user; // save value user to use later on
        return createToken('new', null, user._id);
    }).then(function(token) {
        sUser.tokens.push(token._id); // sUser is user, huzzah
        return sUser.save();
    }).then(function(user) {
        //Do Email Stuff
    }).catch(function(err) {
        // use the content of err to return a meaningful error
        return res.json("something more meaningful based on the content of err");
    });
}

你还应该避免 createToken 中新的 Promise 反模式

var createToken = function(type, expiry, userid) {
    var token = uuid.v4();
    var newToken = Token({
        type:type,
        token: token,
        expiry: expiry,
        user: userid
    });
    return newToken.save();
};

这会产生与您的代码相同的结果

另一种方法是将user 发送到 createToken 函数并像这样重写您的代码

module.exports.register = function(req, res) {
    var input = req.body;
    var newUser = new User ({
        username: input.username,
        email: input.email,
        password: input.password,
        active: false
    });
    newUser.save()
    .then(function(user) {
        return createToken('new', null, user);
    }, function(err) { // optionally change errors to meaningful error messages
        throw "newUser.save failed";
    }).then(function(user) {
        //Do Email Stuff
        // you could throw "email failed" if there's an error
    }).catch(function(err) {
        // err could be "newUser.save failed", "newToken.save failed", "email failed"
        // use the content of err to return a meaningful error
        return res.json("something more meaningful based on the content of err");
    });
}

var createToken = function(type, expiry, user) {
    var token = uuid.v4();
    var newToken = Token({
        type:type,
        token: token,
        expiry: expiry,
        user: user._id
    });
    return newToken.save()
    .then(function(token) {
        user.tokens.push(token._id);
        return user.save();
    }) // you could add the following to make the errors suited to you
    .catch(function(err) {
        throw "newToken.save failed";
    });
};

【讨论】:

  • 我注意到 uve 选择不推荐 bluebird 绑定功能?这是为什么呢?
  • 没有理由。只使用纯js,因为我可以
  • 有没有一种方法可以设置每个 then 承诺中的 err 值可能是什么?你还会一直在回调上使用 Promise 吗?我认为这两种方式看起来都很可怕
  • 我已经更新了答案,展示了如何将err 设置为任何你想要的。回复:Promise vs callback,就个人而言,我不喜欢其中一个
  • 所以你说我可以添加“function(err) {} 到每个然后设置错误消息。你知道任何关于这方面的详细文章,因为我认为我不完全理解如何抛出错误。当你抛出时,它会在 catch 中作为 err 变量返回吗?
猜你喜欢
  • 2019-11-20
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
  • 2017-05-16
相关资源
最近更新 更多