随着事件,发起者提出了一个事件,该事件将由当选的例行程序接收到该事件。接收器指定将从哪些发起人那里收到的事件。
带有回调,完成后的例程通知了呼叫者完成。
所以我很困惑我应该在哪里使用事件,或者我应该在哪里使用回调,因为我可以完成回调事件的工作,但导致了应用程序中创建的许多事件。
编码时应该遵循什么好方法?
事件 - 对于可能发生多次发生的事情。
回调(或承诺) - 对于可能发生的事情。
因此,例如,当您具有调用功能时,因为您需要从某些API中获得的当前温度,该功能应返回承诺或接听回调,以后可以用正确的值(或错误)调用该函数。
另一方面,如果您需要每次更改时要获得新的温度,则该功能应返回事件发射器(或带一个事件处理程序以附加到某些内部内部事件发射极)。
现在,关于何时使用回调以及何时使用Promises的问题更加棘手,因为它们适合相同种类的情况 - 当您想知道某些异步操作的结果时(某些数据或错误))。由于两个在相同情况下都可以使用,让我们考虑两个读取文件内容的示例。
首先,带回调:
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());
}
另一个区别是,如果您具有返回承诺的函数,则可以使用 async function
内部的新await
关键字:
async function x() {
try {
console.log('Data:', await a());
} catch (err) {
console.log('Error:', err);
}
}
您不能将await
与不返回承诺的函数一起使用。
它变得非常方便,例如,当您需要读取文件a.txt
以获取包含的另一个文件名时,然后在更复杂的情况下处理所有错误时读取其他文件并打印其内容。
要将async
和await
与Node V7.x一起使用,您需要使用--harmony
标志,请参阅:
- http://node.green/#async-funtions