首页 > step.js改善回调嵌套,但是无法跨层传递参数

step.js改善回调嵌套,但是无法跨层传递参数

如图,我用的express框架,写的一个路由,把

app.get("/loginForm?**", function (req, res) {
    pool.getConnection(function (err) {
        if (err) { }
        else {
            connection.query("USE userInfo", function (err, rows) {
                //业务逻辑
            });
        }
    });
});    

改写为step模式,即使用中间函数传递值,也没法把req和res传递到最内层connection.query的回调函数里,但是这里业务逻辑会用到res.send()向前端传数据,所以问题来了,怎么跨层传递这个res呢?

有人说直接用就行,我改写了代码如下

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) {
            console.log(err + "--from connection");
            res.send("登录失败,数据库连接错误");
        } else {
            var queryString = "USE userInfo;";
            connection.query(queryString, this);
        }
    },
    function poolSelect(err, rows) {
        if (err) {
            console.log(err);
        } else {
            var selectQuery = "SELECT * FROM users WHERE userName=" + "'" + req.query.username + "'";
            connection.query(selectQuery, this);
        }
    },
    function poolRows(err, rows) {
        if (err) {
            console.log(err + "--from queryString");
            res.send("登录失败,数据库查询错误");
        } else {
            if (rows.length == 0) {
                res.send("登录失败,用户不存在");
            } else {
                if (req.query.password == rows[0].password) {
                    res.cookie("username", req.query.username, {
                        expires: new Date(Date.now() + 900000)
                    });
                    res.send("登录成功");
                } else {
                    res.send("登录失败,密码不正确");
                }
            }
        }
    });

select那层调用connection,还有最内层调用res,req都是undifined
我之前写return是因为this无法传递值,试试return行不行

根据大神的指点,我试了下parallel形式,代码如下

    step(    function appGet(){
        app.get("/loginForm?**",this.parallel());
        pool.getConnection(this.parallel());
        },
    
    function poolUse(req,res,connection,err){
        if (err){
            console.log(err+"--from connection");
            res.send("登录失败,数据库连接错误");
        }else{
            var queryString = "USE userInfo";
            connection.query(queryString,function(err,rows){
                if (err) {
                    console.log(err);
                } else{
                    res.send(rows);
                }
            });
        }
}

);
服务器可以返回数据,然而,如你所见,内层的connection.query就只能写成回调风格了,因为如果你写成this或者别的什么,app.get的res和req就传进去了


从第2段代码来看,是有很多变量不存在于当前作用域,看图上的波浪线

我看了 Step 的说明,有这么一段

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

注意,后面传入的参数是 this.parallel(),这个函数调用返回的应该是一个函数,因为 fs.readFile(filename, callback)

在没传入 this.parallel() 的情况下,返回值,只有 1 个,是作为参数传递给下一个函数的,像你这种情况不能写 n 个 return,因为只有第 1 个起作用,后面的不会执行。你应该这样写

step(
    function step1() {
        return {
            arg1: "arg1",
            arg2: "arg2"
        }
    },
    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]);
        }
    });

但这里有个问题,app.getcallback 是在内部的函数中定义的,其参数不可能 return 出来。如果用 this.parallel(),又不知道它能不能处理多个参数的情况。可能得你自己试试了。

做了个试验,总算知道咋个用 group 来处理多个参数的情况了

function james(callback) {
    callback(null, "james", 30, true);
}

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

你的代码大概应该是下面这个样子,试试

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

终了

想了下,可以用类似 group() 的办法来用 parallel(),反正参数都是自己传的,不用搞那么复杂

function james(callback) {
    callback(null, "james", 30, true);
}

var step = require("step");
step(function () {
    var parallel = this.parallel();
    james(function (error, name, age, isMale) {
        parallel({
            name: name,
            age: age,
            gender: isMale ? "男" : "女"
        });
    });
}, function (args) {
    console.log(args);
});

// 输出
// { name: 'james', age: 30, gender: '男' }

你的代码应该是改成这样(没调试,你自己试试)

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;
            }
            parallel(args);
        })
    },
    function poolUse(args) {
        if (args.err) {
            console.log(args.err + "--from connection");
            args.res.send("登录失败,数据库连接错误");
        } else {
            var queryString = "USE userInfo";
            args.connection.query(queryString, function (err, rows) {
                if (err) {
                    console.log(err);
                } else {
                    args.res.send(rows);
                }
            });
        }
    });
【热门文章】
【热门文章】