This is the 23rd day of my participation in the August More Text Challenge.More challenges in August
The listener
This article is a continuation of NodeJs: Asynchronous I/O (part 1), so you can refer to the previous section for an introduction to listeners, or to the API for instructions
-
The event listener pattern is widely used in asynchronous programming. It is the eventization of callback functions, also known as publish/subscribe pattern.
-
The Events event trigger module provided by Node itself is a simple implementation of the publish/subscribe pattern.
-
All objects that fire events are instances of the EventEmitter class.
Listeners only listen once
You can set the listener to once() so that the listener is called only once and not too much. Once the event is triggered, the listener is deregistered and invoked.
This approach works well for some queries that only need to be executed once, such as SQL queries where new calls to the same call simply wait in the queue for the data to be ready, and the results can be shared by those calls once the query ends. This saves the overhead of repeated calls. Since Node executes single-threaded, there is no need to worry about state synchronization.
myEmitter.once('event2'.(val) = > {
console.log(val);
});
myEmitter.emit('event2'.'hello world! ');
myEmitter.emit('event2'.'ok');
Copy the code
Results:
This listener method can reduce the number of reads while reading file data
The read method is set in IOcode/index.js
When we define the readTxt read method, we set the Promise, so that we can get the return value in the future. If an error occurs or the correct result is returned, we can also directly use the. (PS: Because the work is not packaged and compatible with IE9, ES6 is not available at all. It can only be added from time to time during self-study, and can only be skillfully used by practicing more at ordinary times, miserable 😭)
let status = 'ready'
myEmitter.once('read'.() = > {
status = 'peding'
})
// Use once to enable the interface to access data for the first time
function readTxt(namePath) {
return new Promise((reslove, rejects) = >{
fs.readFile(namePath, function(err, data) {
if (err) {
rejects('wrong');
} else {
if (status === 'ready') {
myEmitter.emit('read');
reslove(data);
} else {
rejects(' '); }}})})}module.exports = { readTxt }
Copy the code
Import IOcode/index.js into the import file using require
var IO = express();
let IoCode = require('./IOcode')
IO.get('/txt'.(req, res) = > {
let dpromise = IoCode.readTxt('./src/a.txt');
dpromise.then((val) = >{
res.json({ d: val.toString() })
}, () = > {
res.end();
})
})
IO.listen('3001'.function(){
console.log("Activated...")})Copy the code
Results:
Listener error event
To handle exceptions, EventEmitter objects perform special processing on error events. Is considered a special case in Node.js
If errors at runtime trigger error events, EventEmitter checks to see if a listener has been added to the error event. If added, the error will be handled by the listener, otherwise it will be thrown as an exception. If the exception is not caught externally, the thread exits.
A sturdyEventEmitter
Instances should be pairederror
Event processing.
If only the error is published, the exception is thrown, the stack trace is printed, and the process terminates
myEmitter.emit('error'.new Error('mistake! '));
Copy the code
If an error listener is set, the listener is turned in to handle the error, and the process can proceed
myEmitter.on('error'.(err) = > {
console.log('this is an error');
})
myEmitter.emit('error'.new Error('mistake! '));
Copy the code
RemoveListener removeListener
Listeners can also be removed actively by removeListener or removeAllListeners
RemoveListener removes specified listeners and removeAllListeners removeAllListeners.
Reference: nodejs. Cn/API/events….
In the example below, the statusChange method has been removed from the myEmitter listener by removeListener and will not be emitted when emit calls read. Example:
let status = 'ready';
let statusChange = () = > {
status = 'peding';
console.log(status);
};
myEmitter.once('read', statusChange)
myEmitter.removeListener('read', statusChange);
myEmitter.emit('read');
Copy the code
RemoveListener removeListener removeListener removeListener removeListener removeListener removeListener removeListener removeListener removeListener
Collaboration scheme between multiple asynchrony
The event publish/subscribe model has its advantages. With higher-order functions, listeners can be added and removed at will as callbacks, which can help developers easily handle business logic that can be added at any time, or isolate business logic to keep the responsibilities of business logic units single.
In general, events and listeners have a one-to-many relationship, but in asynchronous programming, events and listeners can be many-to-one. For example, a business logic relies on multiple results passed through callbacks or events.
Example: A change in variable A of method A must occur after both methods B and C are executed
function A(res) {
console.log('Print result:');
console.log(res);
Object.values(res).map((item) = >{ item(); })}Copy the code
2. Define A higher order function after, then define A done method after return function, pass method A into the callback, set times to 2.
The significance of the above is that when the listener listens to done being called, it can add the incoming key and value to results, and then judge whether method A is executed according to whether the number of attribute names in Results is equal to the set times
let after = function(times, callback) {
let results = {}
return (key, value) = >{
let hasArr = Object.getOwnPropertyNames(results);
if (hasArr.indexOf(key) == -1) {
results[key] = value;
if (hasArr.length == times - 1) { callback(results); }}}}let done = after(2, A)
myEmitter.on('done', done)
Copy the code
3. Define required prerequisite methods B and C
function B() {
myEmitter.emit('done'.'fun1'.() = > { console.log('fun1'); })}function C() {
myEmitter.emit('done'.'fun2'.() = > { console.log('fun2'); })}Copy the code
B and C are then executed, and the execution of A will not be executed until the C method is called
setTimeout(() = >{
IoCode.C();
}, 2000)
IoCode.B();
Copy the code
Results:
Of course, you can also use EventProxy for collaboration between multiple asynchronies. This is a very lightweight tool, but can effectively solve the control of high concurrency and large traffic.
Installation: CNPM install EventProxy or YARN add EventProxy
Var EventProxy = require(‘ EventProxy ‘);
Reference article: eventProxy Solves Callback Pits (Node.js)
Example: EventProxy provides an all() method to subscribe to multiple events, each of which needs to be fired before the listener executes
let ep = new EventProxy();
ep.all('temp'.'home'.function(temp, home) {
console.log(`${temp}: ${home}`);
})
function E() { ep.emit('temp'.10)}function F() { ep.emit('home'.8)}Copy the code
EventProxy also improves exception handling on top of the event publish/subscribe model. Use the fail() method to listen for errors in the event
There are also Promise/Deferred patterns and flow control libraries in asynchronous programming solutions. 👻