当我尝试使用'koa-router'模块进行koa时,我看到了下面的示例代码片段。
app.get('/users/:id', function *(next) {
var user = yield User.findOne(this.params.id);
this.body = user;
});
我的问题是,为什么它在获取用户信息之前才有yield
?为什么不能在没有收益的情况下编码如下有什么主要区别吗?
app.get('/users/:id', function *(next) {
var user = User.findOne(this.params.id);
this.body = user;
});
答案 0 :(得分:3)
星号function *(){}
的功能是生成器功能,允许使用暂停和恢复流程yield
关键字。
没有屈服的发电机功能是没用的,它们是齐头并进的。
在 koa 的幕后工作生成器函数由co库调用,该库处理所有异步操作,抽象 回调/承诺进入库,为您提供更简单的代码。
我在了解您可能会发现有用的生成器时创建了screencast。
答案 1 :(得分:1)
我不认识koa。但它似乎使用和谐发生器(可从节点0.11获得)。
基本上第一部分与:
相同app.get('/users/:id', function *(next) {
var self = this;
User.findOne(this.params.id).then(function(user) {
self.body = user;
});
});
当收益率承诺得到解决时,收益率将返回已实现的值,程序将从那里恢复。 function *(..)
(据我所知)也是一个允许使用yield的特殊构造。
答案 2 :(得分:1)
因为正文将被设置为一个在将来不存在的值。
您可以将yield
视为一种wait
关键字,其中等待行为由Koa基础架构处理。你产生一个承诺,然后Koa等待履行的承诺,然后它再次调用你的生成器(实际上,基于生成器在迭代器上调用next()
),使用promise的已解析值作为{的参数{1}},这意味着它会被分配到next
左侧的变量。
所以在这种情况下,你进行数据库调用,产生对Koa的结果承诺,Koa等待它完成,然后传回分配给变量yield
的已实现值,并且函数运行要么直到下一个产量,要么直到它从底部掉下来。
如果考虑如何在同一请求中处理两个异步任务,可能会更清楚:
user
在这种情况下,你“两次在蹦床上跳跃”。
根据您选择如何考虑这一点,您可以将其视为更具可读性的等同于
app.get('/users/:id', function *(next) {
var user = yield User.findOne(this.params.id);
var data = yield someOtherAsynchronousTaskReturningProimse(user);
this.body = data;
});
我认为你会同意所谓的“基于共同例程”的方法更具可读性。除了允许您以function handle(id) {
User.findOne(id)
.then(function(user) {
someOtherAsynchronousTaskReturningPromise(user)
.then(function(data) {
setDataIntoResponse(data);
});
});
}
方式编写中间件/处理程序之外,这种体系结构的另一个优点是,Koa可以在等待您回来解决的承诺时继续做其他有用的事情。
答案 3 :(得分:0)
KOA使用生成器函数来简化所谓的中间件的注入。来自KOA的网站(http://koajs.com/):
当中间件调用yield next时,函数会挂起并传递 控制到下一个定义的中间件。之后就没有了 中间件执行下游,堆栈将放松和每个 中间件恢复执行其上游行为。
示例:
var app = Koa();
app.use (function* (next) {
this.body = '{';
yield next;
this.body += '}';
});
app.use (function* () {
this.body += 'Hello World!';
});
此网络服务器将使用字符串'{Hello World!}'进行响应。为什么?执行流入第一个生成器函数,将body设置为“{”并暂停在yield next
。执行继续下一个生成器函数并附加“Hello World!”。该函数结束,因此执行流回第一个暂停的位置,附加'}'。
然而,在你的情况下,只要使用yield来传递next
之外的其他内容,它会更复杂一些。例如,在KOA中,您也可以产生承诺。看看这个(我在这里找到:http://blog.stevensanderson.com/2013/12/21/experiments-with-koa-and-javascript-generators/)
app.use(function *() {
var response = yield doHttpRequest('http://example.com/');
this.body = "Response length is " + response.body.length;
});
在此示例中,yield
从异步Http请求传递promise(由辅助函数doHttpRequest完成,此处未显示)。 KOA暂停该功能,直到履行承诺,然后继续执行“this.body = ...”。在你的代码片段中,User.findOne()可能会返回这样的承诺。 (不一定; KOA允许您传回其他类型的对象,请参阅文档。)