我正在编写一个模块,该模块具有使用Promise.all()向多个用户发送电子邮件的承诺。剥离代码,我能够将问题重现为以下片段:

var getPromise = function(data) {
    return new Promise((resolve, reject) => {
        console.log("After Calling:\t\t", data.user);
        setTimeout(function() {
                console.log("While Resolving:\t", data.user);
                return resolve(data);
            },
            Math.random() * 1000);
    });
}

var getAllPromises = function(users, options) {
    var promises = [];
    users.forEach(user => {
        var userSpecificOptions = options;
        // var userSpecificOptions = {};
        userSpecificOptions.user = user;
        promises.push(getPromise(userSpecificOptions));
    });
    return Promise.all(promises);
}

var userlist = ["help", "promises", "are", "tough"];
var commonoptions = {
    str: "something",
}

getAllPromises(userlist, commonoptions)
    .then(data => console.log("Data:\n", data))


这给了我以下输出:

After Calling:       help
After Calling:       promises
After Calling:       are
After Calling:       tough
While Resolving:     tough
While Resolving:     tough
While Resolving:     tough
While Resolving:     tough
Data:
 [ { str: 'something', user: 'tough' },
  { str: 'something', user: 'tough' },
  { str: 'something', user: 'tough' },
  { str: 'something', user: 'tough' } ]


但是,切换userSpecificOptions的声明:

        // var userSpecificOptions = options;
        var userSpecificOptions = {};


得到正确的结果:

After Calling:       help
After Calling:       promises
After Calling:       are
After Calling:       tough
While Resolving:     help
While Resolving:     promises
While Resolving:     are
While Resolving:     tough
Data:
 [ { user: 'help' },
  { user: 'promises' },
  { user: 'are' },
  { user: 'tough' } ]


可能是什么问题?我觉得关于Promises的工作方式可能有些缺失。

最佳答案

您使所有userSpecificOptions实例引用相同的options对象:

var userSpecificOptions = options;


因此,当您分配给userSpecificOptions.user时,实际上是在修改options

相反,您应该复制options

var userSpecificOptions = Object.assign({}, options);


或使用对象文字扩展:

var userSpecificOptions = {...options};


这样,对该特定userSpecificOptions对象的任何更改都不会影响options或任何其他变量。

09-11 19:02