回调函数返回值的问题
ejs.ejs.filters.i8n = function (code, lang) {
var _this = this;
var langPath = path.normalize(consoleConfig.savePath + lang + '.' + consoleConfig.outputFileExt);
fs.access(langPath, fs.R_OK, (err) => {
if (err) throw err;
fs.readFile(langPath, 'utf8', function (err, data) {
var source = JSON.parse(data);
});
});
//source 这里是假设,想将上面异步取回的数据在i8n这个函数中返回,能不能做到,怎么做
return source;
};
16 回复
没法这样搞,你外面得到的一定是undefined,你可以形参里传一个cb,通过cb把resource传出去,这样的话你调用这个函数时实例化这个cb就可以了,不过如果你不想回调套回调,你只能events模块发射事件,或者改写为promise,不知你能否理解(๑• . •๑)
@huangyanxiong01 可以使用事件模块,只是说你这里不涉及到复杂的处理流程,即多个异步逻辑汇总一个结果返回给上层业务逻辑,就没必要大动干戈了,所以这里最简单的做法就是形参里传一个回调,然后通过回调把resource传出去,那你外面调用filter时写个回调函数就拿到resource了,总之,你避不开回调的,除非你用fs模块的同步api,但是这样的话就有损性能了,同步意味着堵住真个线程,而node是单线程的,还有一种折中的方案就是改写成promise罗,用看似同步的代码写异步逻辑
@FoghostCn @fantasticsoul
app.js
const fs = require('co-fs');
app.use(function *(next) {
this.session.lang = Object.isUndefined(this.session.lang) ? config.lang : this.session.lang;
ejs.lang = JSON.parse(yield fs.readFile(path.normalize(consoleConfig.savePath + this.session.lang + '.' + consoleConfig.outputFileExt)));
yield next;
});
template.js
module.exports = function (app) {
i18n = function(key){
console.info(msg);
return "Hello "+msg;
};
ejs(app, {
root: path.join(process.cwd(), 'view'),
layout: false,
//layout: 'template',
viewExt: 'html',
cache: false,
debug: true,
filters :{
i18n : i18n
}
});
/**
* 语言过滤器
* @param code
* @param lang
* @returns {*}
*/
ejs.ejs.filters.i8n = function (code) {
return ejs.ejs.lang[code];
};
return ejs.ejs;
};
原理: 阻塞后面的js 执行, 知道异步的callback被调用, 然后将异步结果同步返回 代码上我也不太懂, 可以看看
- 主要有这个 UV_RUN_ONCE http://docs.libuv.org/en/v1.x/loop.html#c.uv_run
- 和 process._tickDomainCallback https://github.com/nodejs/node/blob/v5.10.1/lib/internal/process/next_tick.js#L108-L132