Step.js improves callback nesting, but cannot pass parameters across layers

  node.js, question

图片描述

As shown in the figure, I used the express framework to write a route that took

app.get("/loginForm?  **", function (req, res) {
 pool.getConnection(function (err) {
 if (err) { }
 else {
 connection.query("USE userInfo", function (err, rows) {
 //business logic
 });
 bracket
 });
 });

Rewrite to step mode, that is, using intermediate functions to pass values, it is impossible to pass req and res to the callback function inside of the innermost connection.query. However, business logic here uses res.send () to pass data to the front end, so the problem arises. How to pass this res across layers?

Some people said that just use it directly. I rewritten the code as follows

step(
 function appGet() {
 app.get("/loginForm?  **", this);
 },
 function poolGet(err, req, res) {
 pool.getConnection(this);
 },
 function poolUse(err, connection, req, res) {
 console.log(div);
 if (err) {
 Log (errplus "-fromconnection");
 Res.send ("Login Failed, Database Connection Wrong");
 } else {
 var queryString = "USE userInfo;"  ;
 connection.query(queryString, this);
 bracket
 },
 function poolSelect(err, rows) {
 if (err) {
 console.log(err);
 } else {
 Var selectquery = "select * fromusers where username =" plus "'"plus req.query.username plus "'";
 connection.query(selectQuery, this);
 bracket
 },
 function poolRows(err, rows) {
 if (err) {
 Log (errplus "-fromquerystring");
 Res.send ("Login Failed, Database Query Error");
 } else {
 if (rows.length == 0) {
 Res.send ("Login Failed, User Does Not Exist");
 } else {
 if (req.query.password == rows[0].password) {
 res.cookie("username", req.query.username, {
 Now () plus 900000
 });
 Res.send ("successful login");
 } else {
 Res.send ("Login Failed, Password Incorrect");
 bracket
 bracket
 bracket
 });

The select layer calls connection, and the innermost layer calls res, req are all undifined
I wrote return earlier because this cannot pass a value. Can I try return?

According to the advice of the great god, I tried the parallel form, the code is as follows

step(    function appGet(){
 app.get("/loginForm?  **",this.parallel());
 pool.getConnection(this.parallel());
 },
 
 function poolUse(req,res,connection,err){
 if (err){
 Log (errplus "-fromconnection");
 Res.send ("Login Failed, Database Connection Wrong");
 }else{
 var queryString = "USE userInfo";
 connection.query(queryString,function(err,rows){
 if (err) {
 console.log(err);
 } else{
 res.send(rows);
 bracket
 });
 bracket
 bracket

);
The server can return data, however, as you can see, the inner connection.query can only be written in callback style, because if you write this or something else, res and req of app.get are passed in

Judging from the code in paragraph 2, there are many variables that do not exist in the current scope. Look at the wavy lines on the graph.

clipboard.png

I read itStepThe explanation, there is such a paragraph

Step(
 // Loads two files in parallel
 function loadStuff() {
 fs.readFile(__filename, this.parallel());
 fs.readFile("/etc/passwd", this.parallel());
 },
 // Show the result when done
 function showStuff(err, code, users) {
 if (err) throw err;
 console.log(code);
 console.log(users);
 bracket
 )

Note that the parameters passed in later arethis.parallel()This function call should return a function becausefs.readFile(filename, callback).

In no incomingthis.parallel()In this case, only one return value is passed to the next function as an argument. In your case, you cannot write n returns because only the first one works and the following ones will not be executed. You should write like this

step(
 function step1() {
 return {
 arg1: "arg1",
 arg2: "arg2"
 bracket
 },
 function step2(args) {
 console.log(args.arg1, args.arg2);
 return [1, 2, 3, 4, 5];
 },
 function (arr) {
 for (var i = 0;  i < arr.length) {
 console.log("line", arr[i]);
 bracket
 });

But there is a problem here.app.getThecallbackIs defined in an internal function, its parameters are not possiblereturnCome out. If usedthis.parallel()And I don’t know if it can handle multiple parameters. Maybe you should try it yourself.

After doing an experiment, I finally know how to use group to deal with multiple parameters.

function james(callback) {
 callback(null, "james", 30, true);
 bracket
 
 var step = require("step");
 step(function () {
 var group = this.group();
 james(function (error, name, age, isMale) {
 console.log("callback", {
 n: name,
 a: age,
 m: isMale
 });
 
 group()(null, name);
 group()(null, age);
 group()(null, isMale);
 });
 }, function(error, args) {
 console.log(args);
 });

Your code should look like this. Try it

step(
 function appGet() {
 var group = this.group();
 app.get("/loginForm?  **", function(req, res) {
 group()(null, req);
 group()(null, res);
 });
 },
 function poolGet(err, args) {
 var req = args[0];
 var res = args[1];
 // pool.getConnection(this);
 });

ending

If you think about it, you can use parallel () in a way similar to group (). anyway, the parameters are passed by yourself, so you don’t have to be so complicated.

function james(callback) {
 callback(null, "james", 30, true);
 bracket
 
 var step = require("step");
 step(function () {
 var parallel = this.parallel();
 james(function (error, name, age, isMale) {
 parallel({
 name: name,
 age: age,
 gender: isMale ?  "Male": "Female"
 });
 });
 }, function (args) {
 console.log(args);
 });
 
 //output
 // {name: 'james', age: 30, gender:' male'}

Your code should be changed to this (no debugging, try it yourself)

step(
 function appGet() {
 var parallel = this.parallel();
 
 app.get("/loginForm?  **", function (res, req) {
 parallel({
 res: res,
 req: req
 });
 });
 },
 function (args) {
 var parallel = this.parallel();
 pool.getConnection(function (err, connection) {
 if (err) {
 args.err = err;
 } else {
 args.connection = connection;
 bracket
 parallel(args);
 })
 },
 function poolUse(args) {
 if (args.err) {
 Log (args.errplus "-fromconnection");
 Args.res.send ("login failed, database connection error");
 } else {
 var queryString = "USE userInfo";
 args.connection.query(queryString, function (err, rows) {
 if (err) {
 console.log(err);
 } else {
 args.res.send(rows);
 bracket
 });
 bracket
 });