在退出之前等待 KOAJS 中的 createWriteStream
Waiting for createWriteStream in KOAJS before exiting
我知道 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...');
});
这不是最优雅的代码,但它可以工作,如果我将辅助函数包装在一个循环中,我可以下载任意数量的文件(最终目标是让这个 API 收到一个 JSON 图片 URL 列表)。然而,我不能做的是 return 管道到调用者的结果,应用程序将始终在该过程完成之前退出。我认为将函数调用包装在 yield 中是答案......但不是。
当您在生成器函数(Koa 处理程序)中时,您使用 yield
等待。
一般模式是将您的异步逻辑提取到一个 return 承诺的函数中,然后在您的路由中产生它。
您的代码的第一个问题是您从未在将其转换为 finished/errored 状态的承诺中使用 reject
和 resolve
。承诺永远不知道何时完成。屈服它永远不会 return 控制回路由,这可能是你将它嵌套在另一个 co
进程中的原因。
在这里,我修复了它,以便它在完成时 resolve()
s,在错误时 reject(err)
s。注意:产生命中 reject(err)
路径的承诺将抛出异常 (err
),您可以在调用站点 try/catch。
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
进程中。实施我上面的 resolve/reject 更改后,只需将整个 co 块替换为顶级 yield pipeRequest(url, filepath)
。
我知道 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...');
});
这不是最优雅的代码,但它可以工作,如果我将辅助函数包装在一个循环中,我可以下载任意数量的文件(最终目标是让这个 API 收到一个 JSON 图片 URL 列表)。然而,我不能做的是 return 管道到调用者的结果,应用程序将始终在该过程完成之前退出。我认为将函数调用包装在 yield 中是答案......但不是。
当您在生成器函数(Koa 处理程序)中时,您使用 yield
等待。
一般模式是将您的异步逻辑提取到一个 return 承诺的函数中,然后在您的路由中产生它。
您的代码的第一个问题是您从未在将其转换为 finished/errored 状态的承诺中使用 reject
和 resolve
。承诺永远不知道何时完成。屈服它永远不会 return 控制回路由,这可能是你将它嵌套在另一个 co
进程中的原因。
在这里,我修复了它,以便它在完成时 resolve()
s,在错误时 reject(err)
s。注意:产生命中 reject(err)
路径的承诺将抛出异常 (err
),您可以在调用站点 try/catch。
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
进程中。实施我上面的 resolve/reject 更改后,只需将整个 co 块替换为顶级 yield pipeRequest(url, filepath)
。