我知道this问题,但我的需求有点不同。
我尝试下载多张图片,但无法阻止该应用在流程完成前退出。我已经经历了很多次迭代,这就是我目前所处的位置:
router
.post('/', koaBody(), function *() {
var images = [];
//console.log(this.request.body.fields);
if (this.request.body.fields) {
images = this.request.body.fields['images'];
imageCount = images.length;
} else {
this.status = 500;
return;
}
var url = 'https://www.google.ca/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png';
var filepath = '../images/image_1.png';
var pipeRequest = function (url, filepath) {
return new Promise(function (resolve, reject) {
request.get(url)
.pipe(fs.createWriteStream(filepath))
.on('finish', function () {
console.log('piped');
});
});
};
co(function*() {
yield pipeRequest(url, filepath);
}).then(function () {
console.log('done co-func');
}).catch(function (err) {
return console.error(err);
});
console.log('App exiting...');
});
它不是最优雅的代码但是它有效,如果我将循环中的co-function包装起来,我可以下载尽可能多的代码(最终目标是让这个API接收一个JSON列表图片网址)。然而,我不能做的是将管道的结果返回给调用者,应用程序将始终在该过程完成之前退出。我认为将函数调用包装在yield中将是答案......但不是。
答案 0 :(得分:2)
当你进入生成器函数(Koa处理程序)时,使用yield
等待。
一般模式是将异步逻辑提取到一个返回一个promise的函数中,然后在你的路径中产生它。
您的代码的第一个问题是,您永远不会在承诺中使用reject
和resolve
将其转换为已完成/错误状态。承诺永远不知道它什么时候结束。产生它永远不会将控制权返回给路径,这可能就是你将它嵌套在另一个co
进程中的原因。
在这里,我修复它以使其resolve()
完成并且reject(err)
出错。注意:产生一个匹配reject(err)
路径的承诺会抛出一个异常(err
),您可以在呼叫站点尝试/捕获。
var pipeRequest = function(url, filepath) {
return new Promise(function(resolve, reject) {
request.get(url)
.pipe(fs.createWriteStream(filepath))
.on('finish', function() { resolve() })
.on('error', function(err) { reject(err) })
});
};
我看到的第二个问题是你在路线中嵌套co
进程,这将确保路由永远不会在其中的yield
上等待。
Koa处理程序已在co
进程内运行。在您实施我的解决/拒绝更改后,只需用顶级yield pipeRequest(url, filepath)
替换整个co块。