V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Rorysky
V2EX  ›  Node.js

第一次写 node.js , 调用 async. waterfall 里进行 mysql 嵌套循环查询, callback is not a function,有偿咨询……

  •  
  •   Rorysky · 2018-04-05 00:45:34 +08:00 · 5465 次点击
    这是一个创建于 2460 天前的主题,其中的信息可能已经有所发展或是发生改变。

    总是提示 callback is not a function …… 难道回调格式错了?

    主要想实现的逻辑是 操作 mysql 数据库,以第一次查询的结果为条件进行第二次查询,以第二次查询结果为条件进行第三次查询。

     promobonus= function (eigencode, callback){
    	async.waterfall([  
    		    function(eigencode,callback){
    			    pool.query(sql+"promocode = ?",[eigencode+''],function(err,subresult1){
    				    	if(err || subresult1.length<1){
    		                err='sql first level quering erro or result is null';
    		                } else {
    		                
    		            };
    		            console.log('1 '+typeof(callback));
    			    		callback(err,subresult1);	  
    				});
    		    },function(subresult1,callback) {
    		    	var sqlele=[],eigenele=[];
    		    	for(var x of subresult1){
    		    		sqlele.push("promocode= ? OR");
    		    		eigenele.push(x.eigencode);
    		    	};
    		    	var sqltmp=sqlele.join(' ');
    		    	var sqlnew=sql+sqltmp.substring(0,sqltmp.length-2);
    
    		    	pool.query(sqlnew,[eigenele+''],function(err,subresult2){
    		    		  if(err || subresult2.length<1){
    		                err='sql second level quering erro or result is null';
    		                } else {
    		              
    		          };
    		          console.log('2 '+typeof(callback));
    		          callback(err,subresult2);	    	
    		    });
    		    },function(subresult2,callback){
    		    	var sqlele2=[],eigenele2=[];
    		    	for(var y of subresult2){
    		    		sqlele2.push("promocode= ? OR");
    		    		eigenele2.push(y.eigencode);
    		    	};
    		    	var sqltmp2=sqlele2.join(' ');
    		    	var sqlnew2=sql+sqltmp2.substring(0,sqltmp2.length-2);
    
    		    	pool.query(sqlnew2,[eigenele2+''],function(err,subresult3){
    		    		if(err || subresult3.length<1){
    		                err='sql third level quering erro or result is null';
    		                } else {
    		       
    		          };
    		          console.log('3 '+typeof(callback));
    		          callback(err,subresult3);	    	
    		    });
    		    }
    	    ], function (err,subresult3) {  
    	    	if(err) {
    	    		console.log(err);
    	    	}
    	    	console.log('4 '+typeof(callback));
    	    	callback(err,subresult3);
    	    });
    };
    
    10 条回复    2018-04-05 20:15:41 +08:00
    helloworld12
        1
    helloworld12  
       2018-04-05 01:09:14 +08:00   ❤️ 1
    用 es6 的 async 和 await 啊 ,不要用这个
    wotemelon
        2
    wotemelon  
       2018-04-05 01:38:13 +08:00   ❤️ 1
    纠正楼上,async await 属于 es7.
    升级 nodejs 到 8 LTS 以上,支持 async await 写法,谁写谁怀孕
    dd0754
        3
    dd0754  
       2018-04-05 01:52:16 +08:00   ❤️ 1
    干嘛不用 async/await,这个看着就蛋疼...

    第一个函数
    function(eigencode,callback)
    改成
    function(callback)
    noe132
        4
    noe132  
       2018-04-05 02:33:48 +08:00   ❤️ 1
    还有空格 tab 混用。。。
    dingtian
        5
    dingtian  
       2018-04-05 03:43:23 +08:00   ❤️ 1
    其实 es6 的 Promise 也可以了解一下。。。
    Rorysky
        6
    Rorysky  
    OP
       2018-04-05 09:44:28 +08:00
    @dd0754 感谢!不报错了; 其实一开始只看了 js 基本语法,第一个版本是用回调嵌套写的…… 感觉写出来简直 shit 一样,改成这个 waterfall 流程控制了……

    再请教一下 为什么把第一个参数 eigencode 去掉就可以了。
    vcfvct
        7
    vcfvct  
       2018-04-05 10:40:48 +08:00 via Android
    都 2018 了,还是直接用 asycn await 吧。。。
    Cbdy
        8
    Cbdy  
       2018-04-05 12:08:08 +08:00 via Android
    @wotemelon 纠正一下,async,await 似乎属于 es2017
    whypool
        9
    whypool  
       2018-04-05 13:40:14 +08:00
    数据库查询,逻辑控制,分开写
    数据表查询返回一个 promise,调用直接 await 就行,不用回调
    zgk
        10
    zgk  
       2018-04-05 20:15:41 +08:00
    写了个楼上提到的 Promise 和 async/await 的示例,希望可以带来帮助

    ```
    // 把回调包装成 Promise
    function run(sql, params) {
    return new Promise(function (resolve, reject) {
    pool.query(sql, params, function (err, data) {
    if (err) return reject(err);
    resolve(data);
    });
    })
    }

    // Promise 方式执行
    run('SELECT * FROM .....')
    .then(function (data) {
    // 第一次查询以后
    return run('SELECT * FROM ....', data.xxx);
    })
    .then(function (data) {
    // 第二次查询以后
    return run('SELECT * FROM ....', data.yyy);
    })
    .then(function (data) {
    // 第三次查询以后
    })
    .catch(function (error) {
    // 错误情况
    console.log(error);
    });

    // async/await 方式
    async function runAsync() {
    try {
    let result1 = await run('SELECT * FROM ....');
    let result2 = await run('SELECT * FROM .... WHERE a = ?', result1.xxx);
    let result3 = await run('SELECT * FROM .... WHERE a = ?', result2.yyy);
    } catch (error) {
    console.log(error);
    }
    }

    runAsync();

    ```

    个人感觉 Promise 的形式假如有中间需要跳出的逻辑的话,手动构造一堆 Promise.resolve() 然后还好多 if 判断不太方便,async/await 舒服多了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1081 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 18:51 · PVG 02:51 · LAX 10:51 · JFK 13:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.