不止一次阻止绑定一个函数

我有一个recursion重试例程,如下所示:

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()调用cb.bind() 。 有没有什么好的方法来做到这一点?

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

我所知道的唯一好的解决scheme是通过一个重试计数,如下所示:

  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); } }: } 

你可以使用局部variables作为绑定版本,所以当你recursion调用自己的时候,你传递原始的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() } 

或者,如果你真的只想绑定一次,那么你可以在一个包装函数中做到这一点,并通过一个假设callback已经绑定的子函数recursion地调用自己:

 // 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); } 

您可以创build一个类variables来指示函数是否被绑定:

 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(); 

由于绑定会遮盖Function.toString()方法中的原始纯文本函数源代码,因此您可以检查string版本以查看是否绑定了用户界面函数:

  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); } } };