使用 Bluebird promises 修复 Node.js 中的 scope/context 错误
Fixing scope/context mistake in Node.js with Bluebird promises
由于 this awesome video playlist,我认为我终于掌握了一些基本的 javascript 概念:回调、作用域和上下文不再是头疼的问题。
然后,我决定使用 promises(Node.js 中的 bluebird)...这些问题再次出现,我想我不明白范围和上下文如何与 promises 一起工作。这是我的测试 运行 :
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
Promise
.delay(5000) // do some async operations...
.then( () => {
console.log(test);
});
}
return("finished");
}
console.log(testit());
//// What I hoped to see :
// 0, 1, 2, finished, 0, 1, 2
//// What happens :
// 0, 1, 2, finished, 2, 2, 2
我又回来了 scope/context 麻烦。为了解决这个问题,我找到了 bluebird Promise.bind()
,它给了我:
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
Promise
.bind(this, test)
.delay(5000)
.then( (test) => {
console.log(test);
});
}
return("finished");
}
console.log(testit());
//// What happens :
// 0, 1, 2, finished, 0, 1, 2
哎呀!我有一个解决方法!但是在链接 .next()
方法时显然不方便:我必须将 test
的值从一个承诺传递到另一个承诺......在我的代码中不能这样做,我在其中链接了很多不同 functions/methods.
那么,在 Node.js 中使用 promises 时,是否有更简洁的方法从 for
循环中 "bind"/"retain some values" ?
编辑:我正在考虑循环内的承诺链的闭包:
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
(function (test){
Promise
.delay(5000) // do some async operations...
.then( () => {
console.log(test);
});
})(test);
}
return("finished");
}
console.log(testit());
//// What happens :
// 0, 1, 2, finished, 0, 1, 2
它也能用,这是我迄今为止最好的代码。但我最初的问题仍然存在:是否有 better/cleaner 方法来实现最初预期的结果?
结论:接受的答案可能是管理循环内异步操作的最干净的方法。使用在循环外声明的闭包函数很可靠。感谢 Rob M. !
闭包是您最好的选择,否则 test
将绑定到父作用域(而不是 Promise
回调的作用域)并且您将继续看到 运行 时间值test
,而不是您想要的通话时间值。
function getPromise(index) {
return Promise
.delay(5000)
.resolve('index: ')
.then((prefix) => {
console.log(prefix + index);
});
}
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
getPromise(i);
}
console.log('finished');
}
.bind
是一种完全可以接受的方法,但如果它更适合您的话
由于 this awesome video playlist,我认为我终于掌握了一些基本的 javascript 概念:回调、作用域和上下文不再是头疼的问题。
然后,我决定使用 promises(Node.js 中的 bluebird)...这些问题再次出现,我想我不明白范围和上下文如何与 promises 一起工作。这是我的测试 运行 :
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
Promise
.delay(5000) // do some async operations...
.then( () => {
console.log(test);
});
}
return("finished");
}
console.log(testit());
//// What I hoped to see :
// 0, 1, 2, finished, 0, 1, 2
//// What happens :
// 0, 1, 2, finished, 2, 2, 2
我又回来了 scope/context 麻烦。为了解决这个问题,我找到了 bluebird Promise.bind()
,它给了我:
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
Promise
.bind(this, test)
.delay(5000)
.then( (test) => {
console.log(test);
});
}
return("finished");
}
console.log(testit());
//// What happens :
// 0, 1, 2, finished, 0, 1, 2
哎呀!我有一个解决方法!但是在链接 .next()
方法时显然不方便:我必须将 test
的值从一个承诺传递到另一个承诺......在我的代码中不能这样做,我在其中链接了很多不同 functions/methods.
那么,在 Node.js 中使用 promises 时,是否有更简洁的方法从 for
循环中 "bind"/"retain some values" ?
编辑:我正在考虑循环内的承诺链的闭包:
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
(function (test){
Promise
.delay(5000) // do some async operations...
.then( () => {
console.log(test);
});
})(test);
}
return("finished");
}
console.log(testit());
//// What happens :
// 0, 1, 2, finished, 0, 1, 2
它也能用,这是我迄今为止最好的代码。但我最初的问题仍然存在:是否有 better/cleaner 方法来实现最初预期的结果?
结论:接受的答案可能是管理循环内异步操作的最干净的方法。使用在循环外声明的闭包函数很可靠。感谢 Rob M. !
闭包是您最好的选择,否则 test
将绑定到父作用域(而不是 Promise
回调的作用域)并且您将继续看到 运行 时间值test
,而不是您想要的通话时间值。
function getPromise(index) {
return Promise
.delay(5000)
.resolve('index: ')
.then((prefix) => {
console.log(prefix + index);
});
}
function testit(){
for (var i=0 ; i<3 ; i++) {
var test = i;
console.log(test);
getPromise(i);
}
console.log('finished');
}
.bind
是一种完全可以接受的方法,但如果它更适合您的话