关于co调用时 Can't set headers after they are sent.的问题
发布于 9 年前 作者 moxiaobei2 3583 次浏览 最后一次编辑是 8 年前 来自 问答

各位好,在异步的方法里我采用了co的方式,具体方式如下:

数据库查询:

query=function (sql,callback){
  pool.getConnection(function(err, connection) {
    if(err){
      console.error("DB connect fail:"+err);
      callback(err,null);
    }
    connection.query("set names "+config.db.charset);//重新设置一下编码类型
    connection.query(sql,function(err, rows,fields) {
      if (err) {
        connection.rollback(function() {
          callback(err,null);
        });
      }
      callback(null,rows);
      connection.release();
      return ;
    });
  });
}

coQuery=function(sql){
  return function(callback) {
    query(sql,callback);
  };
}

调用时如下:

function getCityList(option,callback){
     var sql="select * from tb_city where 1=1";
     return  db.coQuery(sql,callback);
};

app.get("/getCityList",function(req,res){
 co(function*(){
   var x=yield  getCityList(req.query);
   console.log(x);
   res.json(x);
 })();//报错的这行
});

报错: Can’t set headers after they are sent.请问如何解决

7 回复

query里面

callback(err,null);
callback(null,rows);
var x=yield  getCityList(req.query);
console.log(x);

这里的x应该是第一个参数吧。

还有为啥执行两次啊,这里应该会报错把

co(function*(){
		   var x=yield  getCityList(req.query);
		   console.log(x);
		   res.json(x);
	   })();

@yuyang041060120 单个参数是可以这样写的,console.log(x)是没问题的,我去掉这行也是一样的结果。就第一次访问数据是出来的,再刷新一下就报上面的错误了。

@moxiaobei2 你去掉res.json(x);试试看呢

@yuyang041060120 非常感谢你的回答,我需要好好看看用法。

co要求返回的是promise,thunk或者generator,getCityList并没有返回这些类型,所以co不能处理这种情况。 另外,你的程序结构不正确,所以用普通的callback方式也不能得到正确的结果。

function getCityList(option,callback){
     var sql="select * from tb_city where 1=1";
     return  db.coQuery(sql,callback);
};

db.coQuery传递了两个参数,而在db中定义的只有一个参数。 按照现在的写法,你的程序是不能工作的。

我改进了你的程序,换成promise写法,这样co就可以正常的运行了。我使用了bluebird作为promise的库。

var Promise = require("bluebird");
// Note that the library's classes are not properties of the main export
// so we require and promisifyAll them manually
Promise.promisifyAll(require("mysql/lib/Connection").prototype);
Promise.promisifyAll(require("mysql/lib/Pool").prototype);

function query(sql, cb) {
	var rtn = conn.getConnectionAsync()
		.then(function() {
			return conn.queryAsyn('set query')
		})
		.then(function() {
			return conn.queryAsync(sql)
		})
		.spread(function(rows,  fields) {
			return rows;
		})
		.catch(function(err) {
			conn.rollbackAsync();
			throw err;
		})
		.finally(function() {
			conn.releaseAsync();
		});
		return rtn.nodeify(cb);
}

function getCityList(cb) {
	var sql = 'select * from tb_city where 1=1';
	return query(sql, cb);
}

app.get("/getCityList",function(req,res){
	co(function*(){
   		var x=yield  getCityList(req.query);
   		console.log(x);
   		res.json(x);
 	}).catch(function(err) {
		next(err);
	});
});

@eqiuno 这里确实是自己挖的坑,直接去掉callback参数就可以运行的了,ps:我报错的不在于回调本身,在于co最新版本使用写法不对。愧疚。

/getCitylist 都处理完了, co才执行完,要让express等等你的co啊.

回到顶部