Javascript 了解何时使用事件以及何时使用回调
对于事件,启动器引发一个事件,该事件将由选择接收该事件的例程接收。接收器指定它将从哪些启动器接收哪些事件 对于回调,完成后的例程通知调用方完成 因此,我很困惑应该在哪里使用事件,或者应该在哪里使用回调,因为我可以完成回调对事件的处理,但会导致在应用程序中创建大量事件Javascript 了解何时使用事件以及何时使用回调,javascript,node.js,Javascript,Node.js,对于事件,启动器引发一个事件,该事件将由选择接收该事件的例程接收。接收器指定它将从哪些启动器接收哪些事件 对于回调,完成后的例程通知调用方完成 因此,我很困惑应该在哪里使用事件,或者应该在哪里使用回调,因为我可以完成回调对事件的处理,但会导致在应用程序中创建大量事件 编写代码时,使用事件或回调应该遵循什么好方法?事件-用于可能发生多次的事件 回访(或承诺)-对于可能发生一次的事情 例如,当您调用一个函数,因为您需要从某个API获取当前温度时,该函数应该返回一个承诺或获取一个回调,该回调稍后可以使
编写代码时,使用事件或回调应该遵循什么好方法?事件-用于可能发生多次的事件 回访(或承诺)-对于可能发生一次的事情 例如,当您调用一个函数,因为您需要从某个API获取当前温度时,该函数应该返回一个承诺或获取一个回调,该回调稍后可以使用正确的值(或错误)调用 另一方面,如果您调用了一个函数,因为每次它发生变化时都需要获取新的温度,那么该函数应该返回一个事件发射器(或者将事件处理程序附加到某个内部事件发射器) 现在,关于何时使用回调和何时使用承诺的问题有点棘手,因为它们适用于相同的情况——当您想知道某个异步操作(某些数据或错误)的结果时。因为两种情况都是相同的,所以我们考虑两个读取文件内容的例子。 首先,使用回调:
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());
}
});
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);
}
});
function a(cb) {
fs.readFile('a.txt', 'utf-8', (err, data) => {
if (err) {
return cb(err);
}
cb(null, 'a() data: ' + data.trim());
});
如果没有文件,它将打印:
Error: ENOENT: no such file or directory, open 'a.txt'
Data: Contents of a.txt
如果有文件,它将打印:
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);
});
function a() {
return fs.readFile('a.txt', 'utf-8')
.then(data => 'a() data: ' + data.trim());
}
它的工作原理与前面的示例完全相同
对于这个简单的例子,区别可能不是很明显,但是如果您想要一个函数来抽象一些逻辑呢
例如,对于回调:
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());
}
});
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);
}
});
function a(cb) {
fs.readFile('a.txt', 'utf-8', (err, data) => {
if (err) {
return cb(err);
}
cb(null, 'a() data: ' + data.trim());
});
它将打印此
Error: a() error: ENOENT: no such file or directory, open 'a.txt'
或者像这样:
Data: a() data: Contents of a.txt
async function x() {
try {
console.log('Data:', await a());
} catch (err) {
console.log('Error:', err);
}
}
现在,promises的不同之处在于,在附加成功/错误处理程序之前,您可以将其存储在变量中,从函数返回,或者将其作为参数传递给其他函数。例如:
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()
函数时附加回调。你可以在别的地方做
如果您不想更改错误消息,则将使用回调:
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());
}
});
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);
}
});
function a(cb) {
fs.readFile('a.txt', 'utf-8', (err, data) => {
if (err) {
return cb(err);
}
cb(null, 'a() data: ' + data.trim());
});
并承诺:
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);
});
function a() {
return fs.readFile('a.txt', 'utf-8')
.then(data => 'a() data: ' + data.trim());
}
另一个区别是,如果您有一个返回承诺的函数,您可以在异步函数中使用一个新的wait
关键字,如下所示:
Data: a() data: Contents of a.txt
async function x() {
try {
console.log('Data:', await a());
} catch (err) {
console.log('Error:', err);
}
}
不能对不返回承诺的函数使用wait
例如,当您需要读取文件a.txt
以获取其包含的另一个文件名,然后读取该文件并打印其内容,同时在更复杂的情况下处理所有错误时,它会变得非常方便
要对节点v7.x使用async
和wait
,需要使用--harmony
标志,请参阅:
你能帮助我理解我什么时候应该使用callback,什么时候也应该使用promise吗?@Karan通过更多关于callback和promises的示例查看我的更新答案。