2017-02-14 101 views
2

事件發起者引發了一個事件,該事件將被選擇接收該事件的那些例程接收。接收者指定將從哪些發起者接收哪些事件。瞭解何時使用事件以及何時使用回調

使用回調,完成後的例程通知調用者完成。

所以我很困惑我應該在哪裏使用事件或我應該在哪裏使用回調,因爲我可以完成事件的回調,但會導致在應用程序中創建大量事件。

在編碼,使用事件或回調時應遵循什麼樣的好方法?

回答

2

事件 - 對於可能發生多次的事情。

回調(或承諾) - 對於可能發生一次的事情。例如,當你有一個函數需要從某個API獲取當前溫度時,該函數應該返回一個承諾或者進行一個回調,稍後可以用正確的值調用該回調(或者錯誤)。

如果,另一方面,你有你打電話,因爲你需要在每次當它改變時獲得一個新的溫度的函數,那麼這個函數返回一個事件發射器(或採取的事件處理程序附加到一些內部事件發射器)。

現在,關於何時使用回調以及何時使用promise的問題有點棘手,因爲它們適用於相同類型的情況 - 當您想知道某些異步操作的結果時(某些數據或錯誤)。由於兩者都適用於相同的情況,因此我們考慮閱讀文件內容的兩個示例。

首先,回調:

let fs = require('fs'); 
fs.readFile('a.txt', 'utf-8', (err, data) => { 
    if (err) { 
     console.log('Error:', err.message); 
    } else { 
     console.log('Data:', data.trim()); 
    } 
}); 

如果沒有文件時,它會打印:

Error: ENOENT: no such file or directory, open 'a.txt' 

如果有一個文件,它會打印:

Data: Contents of a.txt 

現在,同承諾一樣:

let fs = require('mz/fs'); 
fs.readFile('b.txt', 'utf-8') 
    .then(data => { 
     console.log('Data:', data.trim()); 
    }) 
    .catch(err => { 
     console.log('Error:', err.message); 
    }); 

它和前面的例子完全一樣。

對於這個簡單的例子,差異可能不是很明顯,但如果你想有一個功能抽象出一些邏輯。

例如對於這一點,有回調:

let fs = require('fs'); 
function a(cb) { 
    fs.readFile('b.txt', 'utf-8', (err, data) => { 
     if (err) { 
      return cb('a() error: ' + err.message); 
     } 
     cb(null, 'a() data: ' + data.trim()); 
    }); 
} 
a((err, data) => { 
    if (err) { 
     console.log('Error:', err); 
    } else { 
     console.log('Data:', data); 
    } 
}); 

它將打印用戶可以在本

Error: a() error: ENOENT: no such file or directory, open 'a.txt' 

或者是這樣的:

Data: a() data: Contents of a.txt 

現在,什麼是與承諾不同的是,你可以將它存儲在一個變量中,從一個函數中返回或者將它作爲參數傳遞給其他一些樂趣在附加成功/錯誤處理程序之前。例如:

let fs = require('mz/fs'); 
function a() { 
    return fs.readFile('a.txt', 'utf-8') 
     .then(data => 'a() data: ' + data.trim()) 
     .catch(err => Promise.reject('a() error: ' + err.message)); 
} 
let promise = a(); 
promise.then(data => console.log('Data:', data)) 
     .catch(err => console.log('Error:', err)); 

它的工作原理是相同的,它是用不同的風格,你可能會或可能不會找到更具可讀性,但不同的是,現在你不必在當時附加回調調用a()函數。你可以在別的地方做。

如果您不想更改錯誤信息,這將是這與回調:

function a(cb) { 
    fs.readFile('a.txt', 'utf-8', (err, data) => { 
     if (err) { 
      return cb(err); 
     } 
     cb(null, 'a() data: ' + data.trim()); 
    }); 

,這與承諾:

function a() { 
    return fs.readFile('a.txt', 'utf-8') 
     .then(data => 'a() data: ' + data.trim()); 
} 

另一個區別是,如果你有一個函數返回一個承諾,您可以使用一個新的await關鍵字async function像這樣:

async function x() { 
    try { 
     console.log('Data:', await a()); 
    } catch (err) { 
     console.log('Error:', err); 
    } 
} 

您不能使用await的函數不返回承諾。

例如,當您需要讀取文件a.txt以獲取其中包含的另一個文件名,然後讀取其他文件並在處理更復雜情況下的所有錯誤時打印它的內容時,它非常方便。

要使用asyncawait你需要使用--harmony標誌節點V7.x中,請參閱:

+0

能否請您幫助瞭解何時應使用回調和什麼時候應該使用諾言呢? –

+1

@Karan用更多的回調和承諾示例查看我更新的答案。 – rsp

相關問題