了解何时使用事件以及何时使用回调 [英] Understanding when to use Events and when to use Callback

查看:67
本文介绍了了解何时使用事件以及何时使用回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于事件,启动器会引发一个事件,该事件将由已选择接收该事件的那些例程接收。接收器指定它将从哪些启动器接收哪些事件。

With events, the initiator raises an event that will be received by those routines that have elected to receive that event. The receiver specifies what events it will receive from what initiators.

通过回调,完成后的例程通知调用者完成。

With callbacks, the routine after completion notifies the caller of the completion.

所以我很困惑我应该在哪里使用事件或者我应该在哪里使用回调,因为我可以完成回调对事件的处理,但会导致在应用程序中创建大量事件。

So I am confused where should I use events or where should I use the callbacks as I can accomplish what a callback do with events but resulting in a lot of events created in the application.

在编码,使用事件或回调时应该遵循什么样的好方法?

What should be a good approach to follow while coding, to use events or callbacks?

推荐答案

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

Events - for things that can happen many times.

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

Callbacks (or promises) - for things that can happen once.

因此,例如,当你有一个你调用的函数,因为你需要从某个API获取当前温度时,该函数应该返回一个promise或者接受一个稍后可以用正确的值调用的回调(或者错误) )。

So for example, when you have a function that you call because you need a current temperature taken from some API, that function should either return a promise or take a callback that can later be called with the right value (or error).

另一方面,如果你有一个你打电话的功能,你需要在每次更改时获得一个新的温度,然后这个函数应该返回一个事件发射器(或者将一个事件处理程序连接到一些内部事件发射器)。

If, on the other hand, you have a function that you call because you need to get a new temperature every time when it changes, then this function should return an event emitter (or take an event handler to attach to some internal event emitter).

现在,关于何时使用回调以及何时使用promises的问题有点棘手,因为它们适用于相同类型的情况 - 当你想要知道一些异步操作的结果(一些数据或错误)。由于两者都适用于相同的情况,让我们考虑两个读取文件内容的例子。

Now, the question on when to use callbacks and when to use promises is a little bit more tricky because they are good for the same kinds of situations - when you want to know a result of some asynchronous operation (some data or error). Since both work for the same situations let's consider two examples of reading the contents of a file.

首先,回调:

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());
    }
});

如果没有文件则会打印:

If there is no file it will print:

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);
    });

它的工作原理与前一个示例完全相同。

It works exactly the same as the previous example.

对于这个简单的例子,差异可能不是很明显,但是如果你想要一个抽象出某些逻辑的函数会怎么样。

For that simple example the difference may not be very obvious but what if you wanted to have a function that abstracts some of that logic away.

例如这个,带回调:

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

现在,promises的不同之处在于你可以将它存储在变量中,从函数返回或者在附加成功/错误处理程序之前将其作为参数传递给其他函数。例如:

Now, what is different with promises is that you can store it in a variable, return it from a function or pass it as an argument to some other function before attaching the success/error handlers. For example:

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()函数时附加回调。您可以在其他地方执行此操作。

It works the same, it is written in a different style that you may or may not find more readable, but the difference is that now you don't have to attach a callback at the time of calling the a() function. You can do it somewhere else.

如果您不想更改错误消息,则可以使用回调:

If you didn't want to change the error message, it would be this with callbacks:

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());
}

另一个区别是,如果你有一个返回承诺的函数,你可以在异步函数中使用新的等待关键字,如下所示:

Another difference is that if you have a function that returns a promise, you can use a new await keyword inside of a async function like this:

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

您不能使用 await 带有不返回承诺的函数。

You cannot use await with a function that doesn't return a promise.

例如当你需要读取文件时非常方便a.txt 获取它包含的另一个文件名,然后在更复杂的情况下处理所有错误时读取其他文件并打印其内容。

It gets very convenient for example when you need to read file a.txt to get another filename that it contains, and then read that other file and print its contents while handling all errors in more complex situations.

要使用Node v7.x async 等待,您需要使用 - -harmony flag,见:

To use async and await with Node v7.x you need to use the --harmony flag, see:

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

这篇关于了解何时使用事件以及何时使用回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆