JavaScript范围陷阱与承诺

JavaScript范围陷阱与承诺,javascript,es6-promise,Javascript,Es6 Promise,我有一个数组B包含这样的单词 B=[‘你好’、‘爱’、‘和平’] 我正在尝试创建承诺数组p: for(var i=0;i如果将行初始化移到promise回调的函数范围内,不同的迭代将不会相互影响: B=['hello','love','peace']; P=[]; 对于(变量i=0;i{ var closureBinding=word;//ES3+ 设置超时(()=> 决心({ varBinding, closureBinding, letBinding, 康斯特宾, }), 200 );

我有一个数组B包含这样的单词

B=[‘你好’、‘爱’、‘和平’]

我正在尝试创建承诺数组p:


for(var i=0;i如果将
初始化移到promise回调的函数范围内,不同的迭代将不会相互影响:

B=['hello','love','peace'];
P=[];
对于(变量i=0;i*/
将行移到承诺内

var B= ['hello', 'love', 'peace'] ;
  var P = [] ;
   for(var i = 0; i<B.length; i++){

        var p = new Promise(function(resolve, reject){
           var line = B[i];
            setTimeout(function(){
                resolve(line)},2000
            );
        })
        P.push(p);
    }

    Promise.all(P).then(function(data){
        console.log('data',data);
    })
var B=['hello','love','peace'];
var P=[];

对于(var i=0;i如果使用es6,代码可能如下

让B=['hello','love','peace';
设P=[];

对于(var i=0;i您的问题是
var
声明在JavaScript中被提升到最近的封闭函数块的顶部或文件的顶部。这意味着:

for (/* some loop */) {
  var line = someValue();
}
实际上被翻译成:

var line;
for (/* some loop */) {
  line = someValue();
}
您需要将
var
绑定移动到
new Promise
闭包中,或者使用ES2015+块绑定(
let
const

var words=['hello','love','peace'];
var承诺=[];
为了(让一个字一个字){
让letBinding=word;//ES2015+
const constBinding=word;//ES2015+
var varBinding=word;//ES3+
var p=新承诺(解决=>{
var closureBinding=word;//ES3+
设置超时(()=>
决心({
varBinding,
closureBinding,
letBinding,
康斯特宾,
}),
200
);
})
承诺推送(p);
}

Promise.all(promises).then(data=>console.log('data:',data));
其他es6答案都没有利用
中为
循环使用特殊的作用域规则

只需在for循环语句中使用
let
(尝试运行它):

var B=['hello','love','peace',P=[];
for(设i=0;i设置超时(()=>resolve(B[i]));
P.push(P);
}
Promise.all(P).then(data=>console.log(data));//你好,爱,和平
或使用es7绑定语法:

Promise.all(['hello', 'love', 'peace'].map(::Promise.resolve)).then(::console.log)

太棒了!你能解释一下我的代码不工作的原因吗?区别在于作用域。var的作用域是最近的函数块,let的作用域是最近的封闭块(如果在任何块之外,两者都是全局的),它可以比功能块小。因此您创建了一个非常和平的承诺。除了使用
let
之外,您还应该按照Timosta的建议将
line
转换到
promise
的执行器范围中。这里不需要闭包,因为
line
只是一个辅助变量,不需要存在于父作用域中。
Promise.all(['hello', 'love', 'peace'].map(::Promise.resolve)).then(::console.log)