关于解决数据层异步回调问题
发布于 7 年前 作者 terryjfchen 3621 次浏览 来自 问答

刚开始学习使用nodejs 做后台服务开发,碰到mysql数据处理的问题,一旦涉及数据库操作,我理解都会成为异步,即需要由回调函数返回数据 但是,这么操作的话,一旦一个业务逻辑需要多次查询,回调就很可怕了。 后来改了用async/await来解决这个问题,但是返回的Promis对象,结果上层还是属于异步操作,需要回调,这样的架构就有点奇怪了。如下: client -> web controller -> service -> dao(返回promiss),这样的会,从controller层开始就需要嵌套回调至service层了。是我的理解有误,还是有更好的办法(例如强行阻塞?)

7 回复

强行阻塞,,那你用数据库就biu的一下网站卡在这里了。。。个人觉得复杂的数据库处理逻辑可以考虑建立相关另外的表来简化node的数据库操作,,

啥叫“返回的是Promise对象,上层还是属于异步操作,需要回调,架构奇怪”呀

现在我们开发都统一使用async/await了,跟写同步代码没啥区别。

可以去npm上搜一搜相关module,很多module都把原生API封装成返回promise对象的了。

建议楼主统一使用callback或async/await,同一套代码里不要出现两个都使用的情况,callback可以使用async库,async/await的选择就很多了。

如果代码量太大转换不方便的话,推荐一个库 thenify-all 可以将callback形式接口的代码统一转成同时支持callback和promise的接口(即有传callback就是callback,没传就返回promise,await后的结果为callback参数的数组)

一楼说的也很对,一个业务逻辑涉及多次查询,从架构层面上就应该考虑优化数据库处理逻辑了,而不是从代码上说要多次查询,这样不太好。

强行阻塞就更不行了哈,不符合node的思想。

@Bingmang 还是用代码来描述吧,以下代码中,如果保证两次query是顺序执行并且使用query1中的结果到query2里? exports.query = async function(sqlstr1, sqlstr2) { pool.getConnection(function(err, conn) { await conn.query(sqlstr, function(err, rows, fields) { console.log('Query result: ', rows); });

	await conn.query(sqlstr2, function(err, rows, fields) {
		console.log('Query result: ', rows);
	});
});

};

补充一下,目前我使用了async.waterfall的方法来尝试实现

不需要嵌套回调的,贴一段 dao代码

let list = await this.model.where({status: {"<>": ""}}).select().catch(e => { });
let ps = [], groupModel = think.model('group', {});
if (list.data) {
            list.data.map(item => {
                ps.push(groupModel.where({ id: item.customer_id }).find().then(group => {
                    item.groupname = group.name;
                    return item;
                }));
            });
            await Promise.all(ps);
        }
        return list;
		
		//thinkorm

@richenlin 你这个应该是使用了其他中间件?sequelize?能否展示一下多次查询的代码结构,哪怕都是select 1 from dual也可以

我没有用sequelize,我用的是我们团队封装的orm。还有这个跟orm模块没有关系,即使是使用 node-mysql,一样可以自己使用promisify将回调包装成为promise 然后使用async/await 或者 yield来调用

回到顶部