Bind the `this` scope of a promise callback function

时间:2016-04-07 10:54:21

标签: javascript

Normally if you aren't using promises you can easily do

var a = function(cb){
  setTimeout(function(){
    var boundCb = cb.bind({hello: 'world'});
    boundCb();
  }, 100);
};

a(function(){
  alert(this.hello);
});

which isn't particularly useful most of the times (as you can pass the same things as normal arguments), but it does allow for some extremely readable code and/or simple to use interfaces.

When switching to promises however it suddenly becomes a lot harder to do. Unsurprisingly the following doesn't work (as resolve isn't a direct reference)

var a = function(){
  return new Promise(function(resolve, reject){
    var boundResolve = resolve.bind({hello: 'word'});
    boundResolve();
  });
};

a().then(function(){
  alert(this.hello)
});

so is there any way at all to achieve this?


Non essential postscriptum: 'Luckily' in my situation the this scope I want to set is already the same as what the this scope is at a(). So I am currently simply writing .bind(this) after every single Promise callback function and in the future I will be able to use arrow functions for this, but I am looking for a cleaner solution in the interim.

1 个答案:

答案 0 :(得分:4)

Native Promises不提供此功能。但是,Bluebird Promise库提供 Promise.prototype.bind

以下是一个示例用法

MyClass.prototype.method = function() {
    return fs.readFileAsync(this.file).bind(this)
    .then(function(contents) {
        var url = urlParse(contents);
        return this.httpGetAsync(url); // this is bound to the MyClass instance
    }).then(function(result) {
        // this is still bound, further down the chain.
        var refined = this.refine(result); 
        return this.writeRefinedAsync(refined);
    }).catch(function(e) {
        this.error(e.stack); // Even in event handlers
    });
};