Javascript 防止多次绑定函数
我有一个递归重试例程,如下所示:Javascript 防止多次绑定函数,javascript,node.js,Javascript,Node.js,我有一个递归重试例程,如下所示: 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
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()
。有什么好办法吗
=>我的意思是,有没有办法检查函数是否绑定到某个值
我知道的唯一好的解决方案是通过重试计数,如下所示:
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);
}
}:
}
您可以创建一个类变量,该变量指示函数是否已绑定:
if(!/\[native code\]/.test(cb)) cb = cb.bind(this);
let Foo=function(){
这是。决议=[];
};
Foo.prototype.run=函数(数据,cb){
如果(!this.bound){
console.log('binding');
cb&(cb=cb.bind(this));
this.bound=true;
}
这个.分辨率[x]=(err,val)=>{
如果(val=='foobar'){
//我们在这里重试
返回此.run(数据,cb);
}
};
};
console.log('x');
设x=newfoo();
x、 run();
console.log('y');
设y=newfoo();
y、 run();
console.log('x');
x、 run()代码>您可以创建一个类变量,用于指示函数是否已绑定:
if(!/\[native code\]/.test(cb)) cb = cb.bind(this);
let Foo=function(){
这是。决议=[];
};
Foo.prototype.run=函数(数据,cb){
如果(!this.bound){
console.log('binding');
cb&(cb=cb.bind(this));
this.bound=true;
}
这个.分辨率[x]=(err,val)=>{
如果(val=='foobar'){
//我们在这里重试
返回此.run(数据,cb);
}
};
};
console.log('x');
设x=newfoo();
x、 run();
console.log('y');
设y=newfoo();
y、 run();
console.log('x');
x、 run()
您可以对绑定版本使用局部变量,因此当您递归调用自己时,您将传递原始的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);
}
您可以对绑定版本使用局部变量,因此当您递归调用自己时,可以传递原始的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);
}
由于绑定会使function.toString()方法中的原始纯文本函数源代码变得模糊,因此可以检查字符串版本以查看是否已绑定用户land函数:
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);
}
}
};
由于绑定会使function.toString()方法中的原始纯文本函数源代码变得模糊,因此可以检查字符串版本以查看是否已绑定用户land函数:
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);
}
}
};
为什么要投否决票?请解释为什么你不喜欢这个问题是cb?(cb=cb.bind(this))
valid JS?我不知道你可以在没有替代定义的情况下使用三元函数,我的意思是cb&¬ cb?,对不起,是的,很酷,谢谢你的澄清:)我不认为将函数强制为字符串并对特定的字符串化代码执行正则表达式操作(这似乎是一个暂定的实现细节)是一个好主意。另外,根据您重新运行该函数的次数,您可能会遇到性能下降,因为regex的下行速度慢?请解释为什么你不喜欢这个问题是cb?(cb=cb.bind(this))
valid JS?我不知道你可以在没有替代定义的情况下使用三元函数,我的意思是cb&¬ cb?,对不起,是的,很酷,谢谢你的澄清:)我不认为将函数强制为字符串并对特定的字符串化代码执行正则表达式操作(这似乎是一个暂定的实现细节)是一个好主意。另外,根据您重新运行该函数的次数,您可能会遇到性能问题,因为正则表达式在这种情况下不起作用,因为这是一个有许多实例的类,所以我需要为每个类实例创建一个布尔值。@AlexanderMills,这是一个很好的上下文,可以包含在你的问题中。然后将变量设为propertySummer,你可以看到它是Foo.prototype,这是一个类,但也许我可以澄清编辑在某些情况下会起作用,但在我的情况下不起作用,但我会向上投票,因为它在某些情况下会起作用。在这种情况下不起作用,因为这是一个有很多实例的类,所以我需要为每个类实例创建一个布尔值。@AlexanderMills,这将是一个很好的上下文,可以包含在您的问题中。然后将变量设为propertySummer,您可以看到它是Foo.prototype,这是一个类,但也许我可以澄清Edit在某些情况下会起作用,但它在我的情况下不起作用,但我会向上投票,因为它在某些情况下会起作用。@AlexanderMills-我还添加了另一个选项。第一个解决方案没有优化,因为您将继续调用bind,但只是不在同一个函数上在我的情况下,我不会重试超过3或4次。但一般来说,您不希望继续不必要地调用bind()。所以我认为你的第二个解决方案更好。虽然我更喜欢将这个传递给一个真正私有的运行函数,而不是在原型上运行。@AlexanderMills-这能回答你的问题吗?如果是这样,您可以通过单击答案左侧的绿色复选标记向社区表明这一点,这也将为您赢得一些声誉点数。@AlexanderMills-我还添加了另一个选项。第一个解决方案没有优化,因为您将继续调用bind,但只是不在同一个函数上。在我的情况下,我不打算这样做