我有一个数组B包含这样的单词
B = ['你好','爱','和平']
我正在尝试创建一个Promise数组P:
if (txt.equalsIgnoreCase("yes")) {
...
} else {
...
}
我希望数组数据等于['hello','love','peace'],但实际上数据= ['和平','和平','和平']
我阅读了一些有关JavaScript范围陷阱的帖子,但仍然无法弄清楚如何修复我的代码。
请帮帮我。提前致谢
答案 0 :(得分:1)
如果将line
初始化移动到promise回调的函数范围内,则不同的迭代不会相互影响:
B = ['hello', 'love', 'peace'];
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);
})
/*
data [
"hello",
"love",
"peace"
]
*/
&#13;
<强> Some reading material on JavaScript closures and block vs. function scope. 强>
答案 1 :(得分:1)
如果您使用es6,您的代码可能就像这样
let B = ['hello', 'love', 'peace'];
let P = [];
for(var i = 0; i<B.length; i++){
let line = B[i];
let p = new Promise(function(resolve, reject){
setTimeout(function(){
resolve(line)
},2000);
})
P.push(p);
}
Promise.all(P).then(function(data){
console.log('data',data);
})
如果你使用es5,你应该在功能p {/ p>中var line = B[i];
答案 2 :(得分:0)
在promise
中移动行初始化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);
})
答案 3 :(得分:0)
您的问题是,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 promises = [];
for (let word of words) {
let letBinding = word; // ES2015+
const constBinding = word; // ES2015+
var varBinding = word; // ES3+
var p = new Promise(resolve => {
var closureBinding = word; // ES3+
setTimeout(() =>
resolve({
varBinding,
closureBinding,
letBinding,
constBinding,
}),
200
);
})
promises.push(p);
}
Promise.all(promises).then(data => console.log('data:', data));
&#13;
注销(200ms后):
data: [
{
"varBinding": "peace",
"closureBinding": "hello",
"letBinding": "hello",
"constBinding": "hello"
},
{
"varBinding": "peace",
"closureBinding": "love",
"letBinding": "love",
"constBinding": "love"
},
{
"varBinding": "peace",
"closureBinding": "peace",
"letBinding": "peace",
"constBinding": "peace"
}
]
答案 4 :(得分:0)
其他es6答案都没有利用let
在for
循环中具有特殊范围规则的优势。
只需在for循环语句中使用let
(尝试运行它):
var B = ['hello', 'love', 'peace'], P = [];
for(let i = 0; i<B.length; i++){
var p = new Promise(resolve => setTimeout(() => resolve(B[i])));
P.push(p);
}
Promise.all(P).then(data => console.log(data)); // hello,love,peace
在es6中,let
在每个循环中实例化不同的i
。这是专门为解决这个陷阱而做的。
(陷阱是循环中的单个公共i
在到达setTimeout
的三个回调时间后才会增加到其最终值。)
答案 5 :(得分:0)
Promise.all(
['hello', 'love', 'peace'].map(Promise.resolve.bind(Promise)))
.then(console.log.bind(console))
或使用es7绑定语法:
Promise.all(['hello', 'love', 'peace'].map(::Promise.resolve)).then(::console.log)