async.js resolves the node. js Operation MySQL Callback Tai Hang

Source: Internet
Author: User
Tags bulk insert

Because of the JavaScript language async feature, callback functions are used when using node. js to perform many operations, including accessing the database. If the business logic in the code is a little more complicated, and the callback layer is nested, then the code is easy to get into callback Hell, which is a mental torment for people who write code or who read code.

For example, a transaction operation for MySQL, insert a posts and insert a log:

vartitle =' It is a new post '; Connection.begintransaction ( function(err) {  if(ERR) {ThrowErr } connection.query (' INSERT into posts SET title=? ', title, function(err, result) {    if(ERR) {returnConnection.rollback ( function() {        ThrowErr    }); }varLog =' Post '+ Result.insertid +' added '; Connection.query (' INSERT into log SET data=? ', log, function(err, result) {      if(ERR) {returnConnection.rollback ( function() {          ThrowErr      }); } connection.commit ( function(err) {        if(ERR) {returnConnection.rollback ( function() {            ThrowErr        }); } console.log (' success! ');    });  }); });});

The above very simple business logic has been recalled several layers, if a little more complex, then the code will not be able to look directly.

In order to prevent the large pits where multiple layers of nested callbacks occur, async.js can be used to solve this problem. The following is an introduction to the use of MySQL database with async.js operation.

Async.each BULK Insert

Assuming that the requirement is to insert multiple data into the log table and ultimately return the execution result, you can use the Async.each function:

varSqls = ["INSERT into log SET data= ' data1 '","INSERT into log SET data= ' data2 '","INSERT into log SET data= ' data3 '"];async.each (Sqls, function(item, callback) {  //iterate through each SQL and executeConnection.query (Item, function(err, results) {    if(ERR) {///exception after calling callback and passing in ErrCallback (ERR); }Else{Console.log (item +"Successful Execution");callback is also called when execution is complete, no parameters requiredCallback (); }  });}, function(err) {  //callback after all SQL execution is complete  if(ERR)  {Console.log (ERR); }Else{Console.log ("SQL Full execution succeeded"); }});

Async.each does not guarantee the execution of a successful SQL statement and then executes the next one, so if one execution fails, it does not affect the execution of other statements.

Async.eachseries Batch Inserts sequentially

You can use the Eachseries function if you want to implement the next statement in the array before executing the last statement of the successful execution:

varSqls = ["INSERT into log SET data= ' data1 '","INSERT into log SET data= ' data2 '","INSERT into log SET data= ' data3 '"];async.eachseries (Sqls, function(item, callback) {  //iterate through each SQL and executeConnection.query (Item, function(err, results) {    if(ERR) {///exception after calling callback and passing in ErrCallback (ERR); }Else{Console.log (item +"Successful Execution");callback is also called when execution is complete, no parameters requiredCallback (); }  });}, function(err) {  //callback after all SQL execution is complete  if(ERR)  {Console.log (ERR); }Else{Console.log ("SQL Full execution succeeded"); }});

Async.eachseries guarantees the execution order of SQL, and when one of them executes the exception, it does not proceed to the next one.

Async.foreachof get query results for multiple SELECT statements

Async.foreachof is similar to Async.each, where the difference is that the object type parameter can be received and the key of each entry traversed to the second parameter callback function is passed in, which is more suitable for executing the query statement in bulk and returning the result:

varSqls = {table_a:"SELECT COUNT (*) from table_a", Table_b:"SELECT COUNT (*) from Table_b", Table_c:"SELECT COUNT (*) from Table_c"};//For storing query resultsvarCounts = {};async.foreachof (SQLS, function(value, key, callback) {  //iterate through each SQL and executeConnection.query (Value, function(err, results) {    if(ERR)    {Callback (ERR); }Else{Counts[key] = results[0][' Count (*) '];    Callback (); }  });}, function(err) {  //callback after all SQL execution is complete  if(ERR)  {Console.log (ERR); }Else{Console.log (counts); }});

Operation Result:
{table_a:26, table_b:3, Table_c:2}

Async.map simplifies getting query results for multiple SELECT statements

The code above Async.foreachof gets the query results for multiple SELECT statements can be simplified using the ASYNC.MAP function:

var  sqls = {table_a: " SELECT COUNT (*) from table_a ", Table_b: " SELECT COUNT (*) from Table_b " /span>, Table_c:  "SELECT COUNT (*) from Table_c" };async.map (Sqls, function   (item, callback)  {  connection.query (item, function   (err, results)  { callback (err, Results[0 ][ ' count (*) ' ]); }), function   (err, Results)  { if  (Err) {Console.log (err); } else  {console.log (results); }});

Operation Result:
{table_a:26, table_b:3, Table_c:2}

Async.series perform multiple tasks sequentially

One of the most practical features of async.js is Process control. Back to the beginning of this article, the open transaction execution Insert example, each step requires a successful execution of the previous step to execute, it is easy to fall into the callback pit. The following practical async.series function optimizes process control to make the code more elegant:

vartitle =' It is a new post ';//used to save the auto-generated ID after the posts insert succeedsvarPostID =NULL;//function array, a list of tasks that need to be performed, each function has a parameter callback function and is calledvartasks = [ function(callback) {  //Open transactionConnection.begintransaction ( function(err) {Callback (ERR); });}, function(callback) {  //Insert postsConnection.query (' INSERT into posts SET title=? ', title, function(err, result) {PostID = Result.insertid;  Callback (ERR); });}, function(callback) {  //Insert Log  varLog =' Post '+ PostID +' added '; Connection.query (' INSERT into log SET data=? ', log, function(err, result) {Callback (ERR); });}, function(callback) {  //Commit a transactionConnection.commit ( function(err) {Callback (ERR); });}]; Async.series (Tasks, function(err, results) {  if(ERR)    {Console.log (ERR); Connection.rollback ();//Error occurred transaction rollback} connection.end ();});
Async.waterfall perform multiple tasks sequentially and the next task to get the results of the previous task

The above uses async.series to perform multiple tasks sequentially, but in many cases a task needs to use the relevant data of the previous task, such as inserting a piece of data into the posts table, the ID will be automatically generated, the next insert log will use this ID, if you use the Async.series function to define a Variable var postId to store this ID, you can use Async.waterfall instead of async.series.

vartitle =' It is a new post ';vartasks = [ function(callback) {Connection.begintransaction ( function(err) {Callback (ERR); });}, function(callback) {Connection.query (' INSERT into posts SET title=? ', title, function(err, result) {Callback (err, Result.insertid);//The generated ID is passed to the next task});}, function(Insertid, callback) {  //Receive the ID generated by the previous task  varLog =' Post '+ Insertid +' added '; Connection.query (' INSERT into log SET data=? ', log, function(err, result) {Callback (ERR); });}, function(callback) {Connection.commit ( function(err) {Callback (ERR); });}]; Async.waterfall (Tasks, function(err, results) {  if(ERR)    {Console.log (ERR); Connection.rollback ();//Error occurred transaction rollback} connection.end ();});
Async.series getting results from multiple SQL
//Tasks is an objectvartasks = {table_a: function(callback) {Connection.query (' SELECT COUNT (*) from table_a ', function(err, result) {Callback (Err, result[0][' Count (*) ']);//Pass results to callback}); }, Table_b: function(callback) {Connection.query (' SELECT COUNT (*) from Table_b ', function(err, result) {Callback (Err, result[0][' Count (*) ']);  }); }, Table_c: function(callback) {Connection.query (' SELECT COUNT (*) from Table_c ', function (err, result) {Callback (Err, result[0][' Count (*) ']);  }); }};async.series (Tasks, function(err, results) {  if(ERR)  {Console.log (ERR); }Else{Console.log (results); } connection.end ();});

Operation Result:
{table_a:26, table_b:3, Table_c:2}

These are some of the examples that are often used in the Async.js operations database, and it is no longer necessary to worry about the hole in the async callback. Async.js can be used not only for database operations, but also for other places where asynchronous callback functions are used, such as file reading and writing, this article simply introduces the basic usage of async.js using database operations as an example, and it can be applied to other places where it is needed. In addition to the several functions described above, Async.js also provides some other useful functions, which can be used flexibly in reference to documents.

async.js resolves the node. js Operation MySQL Callback Tai Hang

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.