2017-07-25 83 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); 
     } 
    } 
};