目前场景非常简单,是在router文件中定义了一个generator function,用 yield 调用model文件中的一个方法, 而这个方法本身也是generator function,方法中yield 调用了一些第三方方法。全程thunkify处理。
用readFile模拟代码: 假设这是router中的一个路由,访问model层等待数据返回
var generator1 = function *(next) {
var thunk = thunkify(generator2);
// 程序会在这个地方停住,无法继续前进。
var res = yield thunk(__dirname + '../public/text');
this.body = res;
}
假设这是model层里的函数,操作数据库获得数据,
var generator2 = function *(fd, callback) {
var thunk = thunkify(fs.readFile);
var res = yield thunk(fd);
callback(null, res);
}
程序在注释处停止,没有任何响应,没有报错,程序也在运行,页面在不停等待。 经测试 generator2 函数改写成普通的回调函数,程序就会正常运行。
var generator2 = cb = function (fd, callback) {
fs.readFile(fd, function (err, data) {
callback(null, data);
});
}
不知道是方法不对,还是思路不对,yield就是进不去generator。 写过yield的人应该看过系统提示,可以yield function, generator, array, 等等 不知有没有人遇到过。
我用那个thunkify从来没有对过 自豪地采用 CNodeJS ionic
我自己重新写了一个bluebird的function转promise的函数 你可以到我的github上面去看看 要是觉得麻烦 就直接用bluebird的fromNode方法 在yield 自豪地采用 CNodeJS ionic
@wenshiqi0 谢谢,我去看看。
thunkify
turn a regular node function into one which returns a thunk
而你把generator
传进去,所以得不到期望的结果
var thunk = thunkify(generator2);
为什么会停,下面我的分析 上面那一句,简单地展开大概是下面的形式(粗略表示,不严谨)
var thunk = function(){
var args=Array.prototype.slice.call(arguments);
return function(callback){
args.push(callback);
generator2.apply(null,args);
}
}
所以
var res = yield thunk(__dirname + '../public/text');
大约相当于
var res = yield function(callback){
generator2.apply(null, [_dirname + '../public/text',callback]);
};
当yield
一个函数的时候,co
会把它放promise
里执行
function thunkToPromise(fn) {
var ctx = this;
return new Promise(function (resolve, reject) {
fn.call(ctx, function (err, res) {
if (err) return reject(err);
if (arguments.length > 2) res = slice.call(arguments, 1);
resolve(res);
});
});
}
由于上面的callback
一直没有机会执行,所以co
包装的promise
一直没有结果,所以一直等待
你试试把generator2改成类似这样,然后在generator1里面直接yield不需要thunkify。这里基本的错误是把generator加了回调。generator的一个作用是可以在里面像写同步一样组织异步流程。
var generator2 = function *(fd) { var thunk = thunkify(fs.readFile); var res = yield thunk(fd); return res; }
别混用, 头快炸了
@magicdawn 我想的是既然是用generator处理异步回调,到model层又要用回callback,那就不彻底了。。。
@Hanggi 我用co跑是通过的。实在不行你加上try catch看能不能抓到错误:
var fs = require(‘fs’); var co = require(‘co’); var thunkify = require(‘thunkify’);
var generator2 = function*(fd) { try{ var thunk = thunkify(fs.readFile); var res = yield thunk(fd, ‘utf8’); return res; } catch(e) { console.log(e); return e; } };
var generator1 = function*(next) { var res = yield generator2(__dirname + ‘/test.txt’); console.log(res); };
co(generator1());
另外,你的fd路径是不是有问题呢? __dirname + ‘…/public/text’
@chrischjh 重新试了下,运行成功了。
@Hanggi 我知道,koa跟co在异步管理上类似的,实际上koa应该背后是使用co来组织异步流程的。我相信你用try catch是可以找出错误的,多半是文件路径写的有问题。
如果你非要在那里用generator
. 那应该是这样
var generator1 = function *(next) {
// 由于generator2已经是generator, 所以不必thunkify, 直接 yield
// 由于你想得到yield表达式的值,所以 generator2里面应该把结果 return
var res = yield generator2(__dirname + '../public/text');
this.body = res;
}
// 里面用return
var generator2 = function *(fd) {
var thunk = thunkify(fs.readFile);
var res = yield thunk(fd);
return res;
}
@William17 是的,正常输出了,谢谢。