Home Web Front-end JS Tutorial An in-depth analysis of NodeJs concurrent and asynchronous callback processing_node.js

An in-depth analysis of NodeJs concurrent and asynchronous callback processing_node.js

May 16, 2016 pm 03:24 PM

It is not accurate to say concurrent and asynchronous. It should be said to be continuous asynchronous. The single-threaded asynchronous feature of NodeJs directly causes the callback to be unable to determine the final execution result when multiple asynchronous operations are performed at the same time. Give a simple example:

for(var i = 0; i < 5; i++) {
  fs.readFile('file', 'utf-8', function(error, data){});
} 
Copy after login

I initiated 5 asynchronous operations to read files in a row. It is very simple. So the question is, how can I make sure that all asynchronous operations have been completed? Because the subsequent operations can only be carried out after they are all executed. I believe that students with some experience will think of using counting methods, but how to ensure correct counting is another problem. Think carefully:

Callback is a function that adds 1 to the counter during each asynchronous operation and -1 when each asynchronous operation ends. Determine whether to execute the callback by judging whether the counter is 0. This logic is very simple. It requires a global variable relative to execution time and callback time as a counter, and it must perform a +1 operation when passed to the asynchronous method, and then return a function for callback, which is a bit convoluted, but see See the advanced usage of Js functions:

var pending = (function() {
  var count = 0;
  return function() {
    count++;
    return function() {
      count--;
      if (count === 0) {
        // 全部执行完毕
      }
    }
  }
}); 
Copy after login

When pending is called, it is pending(), for example:

var done = pending(); 
Copy after login

At this time, the counting variable count is initialized to 0, and the returned function is attached to done. If done() is executed at this time, what will happen? Is it to directly execute the first function returned by pending, that is: pending()()? What is this execution? First, the counting variable count+1 is returned, and a function is returned. This function is directly passed as a callback to the asynchronous method. , when executing this callback, first set the count variable count-1, and then determine whether the count is 0. If it is 0, it means that all asynchronous execution is completed, thus achieving continuous asynchronous operations with the same callback.

The key lies in the two returns. Simply put:

The first return function is count+1, and then returns the function that needs callback

The second return function is the function that needs a callback. If it is executed, it will count-1, and then determine whether all asynchronous execution is completed. If it is completed, it will call back

Look at a practical example, asynchronous callback for reading multiple files:

var fileName = ['1.html', '2.html', '3.html'];
var done = pending(function(fileData) {
  console.log('done');
  console.log(fielData);
});
for(var i = 0; i < fileName.lenght; i++) {
  fs.readFile(fileName[i], 'utf-8', done(fileName[i]));
}
Copy after login

The done one uses the pending method to wrap up the method we want to callback and execute. When the counter reaches 0, it will be executed. Then we have to improve the pending method:

var pending = (function(callback) {
  var count = 0;
  var returns = {};
  console.log(count);
  return function(key) {
    count++;
    console.log(count);
    return function(error, data) {
      count--;
      console.log(count);
      returns[key] = data;
      if (count === 0) {
        callback(returns);
      }
    }
  }
}); 
Copy after login

callback is our callback function. When var done = pending(callback), done is actually the first return function. It has a parameter that can be used as the subscript of the returned value, so in the loop body In done(fileName[i]), the file name is passed in. This done() is executed directly. After counting+1, it returns the callback function to be passed to the asynchronous method. As mentioned earlier, this callback function will determine whether to execute the callback function we want to execute based on the count variable. , and pass the contents of the file to it, that is, returns. Okay, let’s run it, I believe we can see the results accurately.

0
1
2
3
2
1
0
done
{"1.html": "xxx", "2.html": "xxx", "3.html": "xxx"}

It can be clearly seen from the count, from 0-3 to 0, and then our callback function outputs done and the contents of the file.

This problem is solved, we need to think about how to encapsulate and reuse such a method. Otherwise, wouldn’t it be unscientific to write pending every time?

Let’s take a look at the processing method of UnJs (one of my NodeJs-based web development frameworks), applied to sub-template operations in template parsing:

unjs.asyncSeries = function(task, func, callback) {
  var taskLen = task.length;
  if (taskLen <= 0) {
    return;
  }
  var done = unjs.pending(callback);
  for(var i = 0; i < taskLen; i++) {
    func(task[i], done);
  }
} 
Copy after login

asyncSeries has three parameters, meaning:

task: The object that needs to be processed, such as the file that needs to be read, it is a list, if it is not a list, or the length of the list is 0, it will not be executed

func: Asynchronous methods, such as fs.readFile, are passed in through it

callback: The method we want to callback

done is the same as before. It is passed to func, but it is not executed. Because we hope that the application side can control the parameters, we let the application side execute it.

Look at the operation when dealing with sub-templates:

var subTemplate = [];
var patt = /\{\% include \'(.+)\' \%\}/ig;
while(sub = patt.exec(data)) {
  var subs = sub;
  subTemplate.push([subs[0], subs[1]]);
}
unjs.asyncSeries(subTemplate, function(item, callback) {
  fs.readFile('./template/' + item[1], 'utf-8', callback(item[0]));
}, function(data) {
  for(var key in data) {
    html = html.replace(key, data[key]);
  }
}); 
Copy after login

The list of subTemplate is data generated based on the analysis of sub-templates. It is a two-dimensional array. The first value of each sub-item is the calling text of the sub-template, that is: {% include 'header.html ' %} such a string, the second parameter is the sub-template file name, that is: header.html

The second parameter of asyncSeries is callback, which is actually the third parameter, which is the pending callback method of the callback function we want to execute. As mentioned earlier, inside asyncSeries, it is not running. Instead, it is run here, that is: callback(item[0]), with parameters, because later the string calling the sub-template in the parent template will be replaced with the content of the corresponding sub-template based on this parameter.

In this way, as long as continuous asynchronous is needed, you can use the asyncSeries method to handle it. Because of the asynchronous relationship, the flow of the program is a bit convoluted, and it may not be easy to understand at first. Even if you are familiar with it, you may suddenly not understand it. It doesn't matter. For example, the callback in the second parameter is actually generated by the third parameter. You may be wondering, what exactly is this callback? There are also two returns in pending, which are not easy to understand and need to be thought about more.

Okay, the continuous asynchronous callback is completed using the advanced features of Js function. However, the asynchronous nature of NodeJs really makes the control of the program very problematic, such as continuous asynchronous operations that require value transfer, etc. These can all be achieved through this idea and changes.

The above content is the knowledge about concurrent and asynchronous callback processing in NodeJs shared by the editor. I hope you like it.

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Best Graphic Settings
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. How to Fix Audio if You Can't Hear Anyone
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25: How To Unlock Everything In MyRise
1 months ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How do I create and publish my own JavaScript libraries? How do I create and publish my own JavaScript libraries? Mar 18, 2025 pm 03:12 PM

Article discusses creating, publishing, and maintaining JavaScript libraries, focusing on planning, development, testing, documentation, and promotion strategies.

How do I optimize JavaScript code for performance in the browser? How do I optimize JavaScript code for performance in the browser? Mar 18, 2025 pm 03:14 PM

The article discusses strategies for optimizing JavaScript performance in browsers, focusing on reducing execution time and minimizing impact on page load speed.

What should I do if I encounter garbled code printing for front-end thermal paper receipts? What should I do if I encounter garbled code printing for front-end thermal paper receipts? Apr 04, 2025 pm 02:42 PM

Frequently Asked Questions and Solutions for Front-end Thermal Paper Ticket Printing In Front-end Development, Ticket Printing is a common requirement. However, many developers are implementing...

How do I debug JavaScript code effectively using browser developer tools? How do I debug JavaScript code effectively using browser developer tools? Mar 18, 2025 pm 03:16 PM

The article discusses effective JavaScript debugging using browser developer tools, focusing on setting breakpoints, using the console, and analyzing performance.

Who gets paid more Python or JavaScript? Who gets paid more Python or JavaScript? Apr 04, 2025 am 12:09 AM

There is no absolute salary for Python and JavaScript developers, depending on skills and industry needs. 1. Python may be paid more in data science and machine learning. 2. JavaScript has great demand in front-end and full-stack development, and its salary is also considerable. 3. Influencing factors include experience, geographical location, company size and specific skills.

How do I use source maps to debug minified JavaScript code? How do I use source maps to debug minified JavaScript code? Mar 18, 2025 pm 03:17 PM

The article explains how to use source maps to debug minified JavaScript by mapping it back to the original code. It discusses enabling source maps, setting breakpoints, and using tools like Chrome DevTools and Webpack.

Getting Started With Chart.js: Pie, Doughnut, and Bubble Charts Getting Started With Chart.js: Pie, Doughnut, and Bubble Charts Mar 15, 2025 am 09:19 AM

This tutorial will explain how to create pie, ring, and bubble charts using Chart.js. Previously, we have learned four chart types of Chart.js: line chart and bar chart (tutorial 2), as well as radar chart and polar region chart (tutorial 3). Create pie and ring charts Pie charts and ring charts are ideal for showing the proportions of a whole that is divided into different parts. For example, a pie chart can be used to show the percentage of male lions, female lions and young lions in a safari, or the percentage of votes that different candidates receive in the election. Pie charts are only suitable for comparing single parameters or datasets. It should be noted that the pie chart cannot draw entities with zero value because the angle of the fan in the pie chart depends on the numerical size of the data point. This means any entity with zero proportion

TypeScript for Beginners, Part 2: Basic Data Types TypeScript for Beginners, Part 2: Basic Data Types Mar 19, 2025 am 09:10 AM

Once you have mastered the entry-level TypeScript tutorial, you should be able to write your own code in an IDE that supports TypeScript and compile it into JavaScript. This tutorial will dive into various data types in TypeScript. JavaScript has seven data types: Null, Undefined, Boolean, Number, String, Symbol (introduced by ES6) and Object. TypeScript defines more types on this basis, and this tutorial will cover all of them in detail. Null data type Like JavaScript, null in TypeScript

See all articles