使用Bluebird承诺修复Node.js中的范围/上下文错误

时间:2016-08-04 17:30:56

标签: javascript node.js promise bluebird

我认为由于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
&#13;
&#13;
&#13;

我在这里,回到范围/上下文的麻烦。为了解决这个问题,我找到了蓝鸟Promise.bind(),它给了我:

&#13;
&#13;
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
&#13;
&#13;
&#13;

Yipee!我有一个解决方法!但是在链接.next()方法时显然不方便:我必须将test的值从一个承诺传递到另一个承诺...在我的代码中不能这样做,我在其中链接许多不同的功能/方法。

那么,是否有一种更清洁的方式来&#34;绑定&#34; /&#34;保留一些值&#34;在Node.js中使用promises时来自for循环?

编辑:我正在思考循环中的promise链的闭包:

&#13;
&#13;
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
&#13;
&#13;
&#13;

它也有效,而且这是我迄今为止最好的代码。但我最初的问题仍然存在:是否有更好/更清洁的方法来实现最初预期的结果?

结论:接受的答案可能是管理循环内异步操作的最简洁方法。使用在循环外部声明的闭包函数。 Thx Rob M.!

1 个答案:

答案 0 :(得分:1)

闭包是最好的选择,否则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是一种完全可以接受的方法,但如果这对您更有效