2017-07-25 67 views
1

更多我有一个递归重试例行程序,这样的事情:防止绑定功能不止一次

Foo.prototype.retry = function(data, cb){ 

    cb && (cb = cb.bind(this)); // want to bind the cb fn just once 

    this.resolutions[x] = (err, val) => { 

     if(val === 'foobar'){ 
     // in this case, we do a retry 
     return this.retry(data, cb); 
     } 

    }: 

} 

,你可以看到,在某些情况下,我会再次调用this.run重试。但我想避免多次拨打cb.bind()。有没有什么好的方法可以做到这一点?

=>我的意思是,有没有办法以某种方式检查函数是否绑定到某个this值?

只有很好的解决,我知道的是通过重试次数,就像这样:

Foo.prototype.retry = function(data, cb){ 

     if(cb){ 
     if(!data.__retryCount){ 
      cb = cb.bind(this); 
     } 
     } 

     this.resolutions[x] = (err, val) => { 

      if(val === 'foobar'){ 
      // we do a retry here 
      data.__retryCount = data.__retryCount || 0; 
      data.__retryCount++; 
      return this.retry(data, cb); 
      } 

     }: 

    } 
+2

为什么downvote?请解释你为什么不喜欢这个问题 –

+0

是'cb? (cb = cb.bind(this))'有效的JS?我不知道你可以做一个三元没有一个替代定义 –

+2

我的意思是cb &&不是cb?,对不起错字 –

回答

2

您可以创建一个类变量,它表示该功能是否已经绑定:

let Foo = function() { 
 
    this.resolutions = []; 
 
}; 
 

 
Foo.prototype.run = function(data, cb) { 
 
    if (!this.bound) { 
 
    console.log('binding'); 
 
    cb && (cb = cb.bind(this)); 
 
    this.bound = true; 
 
    } 
 

 
    this.resolutions[x] = (err, val) => { 
 
    if (val === 'foobar') { 
 
     // we do a retry here 
 
     return this.run(data, cb); 
 
    } 
 
    }; 
 
}; 
 

 
console.log('x'); 
 
let x = new Foo(); 
 
x.run(); 
 

 
console.log('y'); 
 
let y = new Foo(); 
 
y.run(); 
 

 
console.log('x'); 
 
x.run();

+0

在这种情况下不起作用,因为这是一个有很多实例的类,我需要为每个类实例创建一个布尔值。 –

+1

@AlexanderMills,这将是包括在你的问题中的好上下文。 –

+0

然后让变量属性 –

4

您可以使用本地变量绑定的版本,所以当你递归调用自己,你通过原厂升cb,不绑定的一个:

Foo.prototype.run = function(data, cb){ 

    let callback = (cb && cb.bind(this)) || function() {}; 

    this.resolutions[x] = (err, val) => { 
     if(val === 'foobar'){ 
     // we do a retry here and pass original cb 
     return this.run(data, cb); 
     } 
    }; 

    // then elsewhere in this function when you want to use the bound one, use callback() 
} 

或者,如果你真的只想过绑定一次,那么你可以做,在一个包装函数和递归调用自己通过一个子功能假设回调已经绑定:

// internal function, assumes callback is already bound 
Foo.prototype._run = function(data, cb){ 
    // cb is already bound here 
    this.resolutions[x] = (err, val) => { 
     if(val === 'foobar'){ 
     // we do a retry here 
      return this._run(data, cb); 
     } 
    } 

} 

// bind the callback and then call our internal function 
Foo.prototype.run = function(data, cb){ 
    let callback = (cb && cb.bind(this)) || function() {}; 
    return this._run(data, callback); 
} 
+0

这将工作:)良好的思维 –

+0

@AlexanderMills - 我又增加了一个选项。 – jfriend00

+0

感谢您在这里的工作 –

1

由于结合从Function.toString()方法掩盖了原始的纯文本功能的源代码,您可以检查字符串版本,看看用户用地功能已经绑定:

if(!/\[native code\]/.test(cb)) cb = cb.bind(this); 

注意不能使用像console.logwindow.alert已本地方法的这种做法,但是这可能不是你的用例的问题。

全部业务:

Foo.prototype.retry = function(data, cb){ 
    if(!/\[native code\]/.test(cb)) cb = cb.bind(this); // bind the cb fn just once 
    this.resolutions[x] = (err, val) => { 
     if(val === 'foobar'){ 
     // in this case, we do a retry 
     return this.retry(data, cb); 
     } 
    } 
};