在退出之前等待KOAJS中的createWriteStream

时间:2015-12-16 18:59:48

标签: javascript generator koa

我知道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中将是答案......但不是。

1 个答案:

答案 0 :(得分:2)

当你进入生成器函数(Koa处理程序)时,使用yield等待。

一般模式是将异步逻辑提取到一个返回一个promise的函数中,然后在你的路径中产生它。

您的代码的第一个问题是,您永远不会在承诺中使用rejectresolve将其转换为已完成/错误状态。承诺永远不知道它什么时候结束。产生它永远不会将控制权返回给路径,这可能就是你将它嵌套在另一个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块。