[英]Prevent binding a function more than once
I have a recursive retry routine, something like this: 我有一个递归重试例程,如下所示:
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);
}
}:
}
as you can see, under certain circumstances, I will retry by calling this.run
again. 如您所见,在某些情况下,我将再次调用
this.run
重试。 But I would like to avoid calling cb.bind()
more than once. 但是我想避免
cb.bind()
调用cb.bind()
。 Is there any good way to do that? 有什么好办法吗?
=> What I mean, is there a way to somehow check a function is bound to a certain this
value? =>我的意思是什么,有没有办法以某种方式检查被绑定到特定的函数
this
价值?
The only good solution I know of is to pass a retry count, like so: 我知道的唯一好的解决方案是传递一个重试计数,如下所示:
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);
}
}:
}
You can use a local variable for the bound version so when you call yourself recursively, you pass the original cb
, not the bound one: 您可以对绑定版本使用局部变量,以便在递归调用自己时传递原始
cb
,而不是绑定的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()
}
Or, if you really only want to ever bind it once, then you can do that in a wrapper function and call yourself recursively via a sub-function that assumes the callback is already bound: 或者,如果您确实只想绑定一次,则可以在包装函数中执行此操作,并通过一个假定回调已绑定的子函数递归调用自己:
// 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);
}
You can create a class variable which indicates whether or not the function has been bound: 您可以创建一个类变量,以指示该函数是否已绑定:
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();
Since binding obscures the origional plain-text function source code from the Function.toString() method, you can inspect the string version to see if a user-land function has been bound: 由于绑定使Function.toString()方法的原始纯文本函数源代码模糊不清,因此您可以检查字符串版本以查看是否已绑定用户界面函数:
if(!/\[native code\]/.test(cb)) cb = cb.bind(this);
Note you can't use this approach on already native methods like console.log
or window.alert
, but that's probably not an issue for your use-case. 请注意,您不能在本机方法(例如
console.log
或window.alert
上使用此方法,但这对您的用例而言可能不是问题。
in whole: 整体上:
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);
}
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.