【问题标题】:Mutable variable is accessible from closure with promise and loop可变变量可以从带有承诺和循环的闭包中访问
【发布时间】:2015-08-11 08:16:56
【问题描述】:

我使用以下代码为用户生成唯一令牌。用户的数据存储在 MongoDB 上,所以我使用 promise 来处理与数据库的异步对话。在 WebStorm 中,我收到了这个警告:Mutable variable is accessible from closure with promise and loop.,我知道在 SO 上有关于这件事的帖子,但我的情况更复杂。我知道我什至不需要担心它,因为我只使用token 的最后一个值,但我想以正确的方式解决这个问题?

  var generateToken = function(userId) {
        User.findOne({userId: userId}, function(err, user) {
            if (user !== null) {
                var loop = true;
                while (loop) {
                    var token = Common.randomGenerator(20);
                    User.find({tokens: token}, function(err, result) {
                        if (err) {
                            loop = false;
                            return Promise.reject('Error querying the database');
                        } else {
                            if (result.length === 0) {
                                if (user.tokens === undefined){
                                    user.tokens.push(token);
                                }
                                loop = false;
                                return Promise.resolve(token);
                            }
                        }
                    });
                }
            } else {
                return Promise.reject('UserNotFound');
            }
        });
   };

我想出了以下解决方案,是否正确?

var generateToken = function(userId) {
    User.findOne({userId: userId}, function(err, user) {
        if (user !== null) {
            var loop = true;
            while (loop) {
                var token = Common.randomGenerator(20);
                (function(e){
                    User.find({tokens: e}, function(err, result) {
                        if (err) {
                            return Promise.reject('Error querying the database');
                        } else {
                            if (result.length === 0) {
                                if (user.tokens === undefined){
                                    user.tokens = [];
                                }
                                user.tokens.push(e)
                                return Promise.resolve(e);
                            }
                        }
                    });
                })(token);
            }
        } else {
            return Promise.reject('UserNotFound');
        }
    });
};

注意 正如@Alex Nikulin 建议的那样,我在发回承诺结果之前将loop 翻转为false。但它仍然是一个无限循环,因为它没有进入User.find({tokens: e})....

【问题讨论】:

  • loop 什么时候结束?
  • 当函数返回时
  • 你为什么认为,你不进入 User.find({tokens: e}) .....你没有解决承诺?或者你写了 console.log ?
  • 你永远不会在你的代码中得到承诺,因为你在回调中返回承诺,而不是在主函数中。

标签: javascript loops closures promise


【解决方案1】:

您的问题是,return 语句在函数内,而不是在循环内。您的循环是无限的。我已经分解了你的代码。或者当你解决/拒绝承诺时,让循环为假。此外,我的代码将等待用户的每个回答,错误就会消失。并且您的带有 wrap 功能的变体是正确的(function(e){})(token)

var generateToken = function(userId) {
        return new Promise(function(resolve, reject) {
                User.findOne({userId: userId}, function(err, user) {
                    if (user !== null) {
                            userTokenIterator(user,resolve, reject);   
                        } else {
                            reject('UserNotFound');
                        }
                });
        });
       };

    var addTokenToUser = function(token,user){
            return new Promise(function(resolve, reject) {
                      User.find({tokens: token}, function(err, result) {
                        if (err) {
                                reject('Error querying the database');
                        } else {
                                   var result = result.length === 0;
                                if (result) {
                                      if(!user.tokens)  {
                                             user.tokens = []
                                      }
                                      user.tokens.push(token);
                                 } 
                                    resolve(result);    
                        }
            });
            }); 
    };
    var userTokenIterator = function (user, resolve, reject){
            var token = Common.randomGenerator(20);
        addTokenToUser(token, user).then(function(result){
                  if(result) {
                      resolve(token);
                  }else{ 
                      userTokenIterator(user,resolve, reject)
                  }                     
            },function(error){
                   reject(error);
            }); 
    };

【讨论】:

  • 其实我做到了,还是死循环!因为它没有进入User.find({tokens: e})....,我不知道为什么
  • 您正在使用递归方法,这对我来说并不理想,因为它会消耗时间/空间。你可以让它迭代吗?
猜你喜欢
  • 2014-10-27
  • 2015-09-18
  • 2021-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多