JavaScript Promises :带有 bind(this) 的深层嵌套上下文

问题描述 投票:0回答:3

因为我使用的原型具有调用同一原型中其他函数的函数,所以我必须使用

this

引用该方法

问题

this
创建:

但正因为如此,我必须保留一个上下文来使用

this
,这让我形成了非常丑陋的
.bind(this)
墙。

这是我为了搞笑而制作的一个简化示例。

Killmyself.prototype.fireLeMissles = function () {

    return new Promise(function(resolve,reject) {
        this.anotherFunction(param).then(function(result) {

        someList.forEach(function(item) {
          this.fireLeMissles().then(function(anotherResult){
            promiseList.push(anotherResult)
          })
        },this);
        Promise.all(promiseList).then(function(promiseItem){
          childPlacesIds.forEach(function(childPlaceId) {
            //Do Other Stuff
          },this);
        });
      resolve(result);
    }.bind(this).catch(function(err){
      console.log("Yea, life sucks sometimes.")
    }));
  }.bind(this));
}

Killmyself.prototype.another = function(){
   //Other stuff
}

您可以看到,由于调用同一原型中的函数,例如

this.anotherFunction(
...和
this.fireLeMissles(
...我必须深度保存上下文,现在(在我的更大版本中)正在制作这段代码很难使用。

问题:

这是一个“勇敢地面对 JavaScript 的困难方面”的事情 - 还是经验丰富的开发人员看到了可以避免这样的深度绑定的简单方法?

javascript promise ecmascript-6 es6-promise
3个回答
16
投票

如果您使用ES6,您可以受益于箭头函数,它保留了上下文。

var counter = function () {
    this.count = 0;
    setInterval( () => { // arrow function
        console.log(this.count++); // context is preserved
    }, 1000)
}
var counter = new counter();

所以,你的代码会变成这样:

Killmyself.prototype.fireLeMissles = function() {
    return new Promise((resolve, reject) => {
        this.anotherFunction(param).then(result => {
            someList.forEach(item => {
                this.fireLeMissles().then(anotherResult => {
                    promiseList.push(anotherResult)
                });
            });
            Promise.all(promiseList).then(promiseItem => {
                childPlacesIds.forEach(childPlaceId => {
                    //Do Other Stuff
                });
            });
            resolve(result);
        }).catch(err => {
            console.log("Yea, life sucks sometimes.")
        });
    });
}

对于 ES5,您可以完全按照您的方式使用

.bind
,也可以将
this
分配给函数中具有所需上下文的其他内容,然后在内部函数中使用该变量。

Killmyself.prototype.fireLeMissles = function() {
    var self = this; /// use `self` instead of `this` from now on.
    return new Promise(function(resolve, reject) {
        self.anotherFunction(param).then(function(result) {
            someList.forEach(function(item) {
                self.fireLeMissles().then(function(anotherResult) {
                    promiseList.push(anotherResult)
                })
            });
            Promise.all(promiseList).then(function(promiseItem) {
                childPlacesIds.forEach(function(childPlaceId) {
                    //Do Other Stuff
                });
            });
            resolve(result);
        }).catch(function(err) {
            console.log("Yea, life sucks sometimes.")
        });
    });
}

2
投票

对于初学者来说,我不明白你在这里需要一个

new Promise..
,就像@loganfsmyth所说,我会简单地使用箭头函数并降低复杂性:

Killmyself.prototype.fireLeMissles = function (param) {

  return this.anotherFunction(param)
  .then(someList => {
    var promiseList = someList.map( item => this.fireLeMissles(item));
    return Promise.all(promiseList);
  }).then(childPlacesIds => {
    childPlacesIds.forEach(childPlacesId = {
      // .... do something;
    });
    // return something.
  }).catch(err => console.log("Yea, life sucks sometimes."));

}

P。 S:我不确定这个

param, someList, childPlacesIds
来自哪里,并假设您正在将
promiseList
初始化为空数组。


0
投票

Mido 的答案很好,我只是想提供一种替代方案,我认为了解它会很有用 - 使用承诺作为代理:

Killmyself.prototype.fireLeMissles = function () {
  let fn = this.anotherFunction(param);
  let others = fn.then(_ => someList.map(this.fireLeMissles, this));
  let othersP = Promise.all(others);
  othersP.then(/* do OtherStuff */);
  return othersP; // or whatever its then returned
}

当然,使用像 bluebird 这样的库,这会变得更加容易。

© www.soinside.com 2019 - 2024. All rights reserved.