2017-10-13 107 views
0

我試圖調用一個MySQL查詢內部函數,但每次我調用這個函數,我收到這樣的:this.test是不是一個函數無法獲取功能以外範圍

query: function(db) { 
    db.query("SELECT * FROM test", function(err, result, fields) { 
     if (err) throw err; 
     for (var r = 0; r < result.length; r++) { 
      this.test(); 
     } 
    }); 
}, 
test: function(){ 
    console.log("test"); 
} 

做什麼我需要更改我的代碼?

謝謝。

回答

2

您需要在關閉中捕獲this"that"模式通常用於這一目的:

query: function(db) { 
    var that = this; 
    db.query("SELECT * FROM test", function(err, result, fields) { 
     if (err) throw err; 
     for (var r = 0; r < result.length; r++) { 
      that.test(); 
     } 
    }); 
}, 
test: function(){ 
    console.log("test"); 
} 

正如其他人正確地指出的那樣,你可以使用箭頭功能以及。然後在that變量沒有必要:

query: function(db) { 
    db.query("SELECT * FROM test", (err, result, fields) => { 
     if (err) throw err; 
     for (var r = 0; r < result.length; r++) { 
      this.test(); 
     } 
    }); 
}, 
2

現代的方式ES6來解決這個問題(這是在node.js中可用),是使用箭頭函數定義爲回調保存的this值。

query: function(db) { 
    db.query("SELECT * FROM test", (err, result, fields) => { 
     if (err) throw err; 
     for (var r = 0; r < result.length; r++) { 
      this.test(); 
     } 
    }); 
}, 
test: function(){ 
    console.log("test"); 
} 

默認情況下,任何函數調用重置的this基於函數是怎麼被調用的值。所以,當db.query()調用您的回調函數時,原始值this會丟失,並且在回調中不可用。使用ES6箭頭語法聲明這樣的回調函數特別指示Javascript解釋器在執行箭頭函數聲明的回調時保持this(代碼在本地作用域中的值)的詞彙值。


爲了完整起見,有幾種方法可以解決這個問題。

  1. 使用箭頭功能declaraing回調,而不是常規的函數聲明
  2. 保存的this來,你可以參考,而不是this這就是伊戈爾的回答顯示了一個局部變量的值。
  3. 在回調使用.bind(this)來強制回調
  4. this值創建的this.test()一個綁定的版本,您可以在任何地方調用與測試重新綁定this這樣你就可以調用,甚至無法使用this回調中。

在ES6,2和3之前是常用的解決方法。有了ES6,箭頭功能通常是這樣做的首選方式。


同時,請意識到:

if (err) throw err; 

異步回調裏面是不是有效的或有用的錯誤處理。要編寫好的可靠代碼,您需要編寫真正的錯誤處理並確定應用程序在出現此類錯誤時應實際執行的操作。您也可能會發現,對所有異步操作使用promise可以更輕鬆地將異步錯誤傳播回容易處理它們的地方。

+0

@FSantos - 既然你接受了'var that = this'這個答案,我想確保你看到了其他的選項,包括ES6箭頭聲明,這些選項真的是現在更受歡迎的選項。 – jfriend00