Bluebird Promise Scope

爷,独闯天下 提交于 2019-12-20 05:32:12

问题


I have just started using promises in attempt to cleanup some 'callback hell'.

I've decided on trying bluebird and I am running it in the browser but immediately ran into scoping problems.

Is there a way of setting the thisArg in a new Promise? The below example shows that the 'this' value inside the promise resolver is set to the browser window, but I'd like it set to the surrounding scope so I can easily access member variables.

I noticed there is a .bind() method but it only scopes the 'then()' method, not the promise. I also realize I can have 'var me = this' just before the promise and use closure, but I wanted to avoid it if possible.

function MyObject() {
    this.value = 7;
}

MyObject.prototype.getValue = function () {
    return new Promise(function (resolve) {
        // some request/processing that takes a long time
        var result = Ajax.request(...);

        resolve({
            value: this.value,
            result: result
        });
        // 'this' is set to window instead of the instance,
        // resulting in this.value as undefined
    });
}

var obj = new MyObject();
obj.getValue().then(function (value) {
    console.log(value); // preferably outputs 7
})

回答1:


No, there is not. You can of course use the default approaches, but you shouldn't need to.

When doing heavy processing and getting back the value asynchronously, you want to get a promise for the value. You don't need to set the result value as a property of the original instance.

MyObject.prototype.getValue = function () {
    return new Promise(function(resolve) {
        // lots of processing to make a `value`
        resolve(value); // no `this` at all!
    });
};

In case you want to synchronously get the .value that you had set on the instance, you don't need the Promise constructor. Just use Promise.resolve to make a promise for an existing value:

MyObject.prototype.getValue = function () {
    // TODO: lots of processing
    return Promise.resolve(this.value);
};

Or, in your case, even Promise.method:

// TODO: lots of processing
MyObject.prototype.getValue = Promise.method(function () {
    return this.value;
});



回答2:


This is more a comment then an answer, as it is primary opinion based.

In the rar situations where I need this it would look like this in my code:

Ajax.requestAsync in this case would be a promisifyed version of Ajax.request.

I know this might just move your problem to another place.

MyObject.prototype.getValue = function () {
    return Ajax.requestAsync(...)
    .bind(this)
    .then(function(result) {
        return {
              value: this.value,
              result: result
            }
    });
}

Or something like this:

 MyObject.prototype.getValue = function () {
    var returnValue = {
        value: this.value
    };

    return Ajax.requestAsync(...)
    .then(function(result) {
        returnValue.result = result;
        return returnValue;
    });
}

A rarely use such constructs:

MyObject.prototype.getValue = function () {
  return Promise.all([this, Ajax.requestAsync(...)])
  .spread(function(object, result) {
      return {
        value: object.value,
        result: result
      };
  });
}


来源:https://stackoverflow.com/questions/25810728/bluebird-promise-scope

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!