了解何时使用事件以及何时使用回调



随着事件,发起者提出了一个事件,该事件将由当选的例行程序接收到该事件。接收器指定将从哪些发起人那里收到的事件。

带有回调,完成后的例程通知了呼叫者完成。

所以我很困惑我应该在哪里使用事件,或者我应该在哪里使用回调,因为我可以完成回调事件的工作,但导致了应用程序中创建的许多事件。

编码时应该遵循什么好方法?

事件 - 对于可能发生多次发生的事情。

回调(或承诺) - 对于可能发生的事情。

因此,例如,当您具有调用功能时,因为您需要从某些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以获取包含的另一个文件名时,然后在更复杂的情况下处理所有错误时读取其他文件并打印其内容。

要将asyncawait与Node V7.x一起使用,您需要使用--harmony标志,请参阅:

  • http://node.green/#async-funtions

最新更新