我有一个递归重试例程,如下所示:
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);
}
}:
}
答案 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);
}
答案 1 :(得分: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();

答案 2 :(得分:1)
由于绑定模糊了Function.toString()方法中的原始纯文本函数源代码,因此您可以检查字符串版本以查看是否已绑定用户区函数:
if(!/\[native code\]/.test(cb)) cb = cb.bind(this);
请注意,您无法在console.log
或window.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);
}
}
};