为什么 promise-limit 在 Nodejs 中不起作用?
Why is promise-limit not working in Nodejs?
我有大量图片要下载。我正在使用 request-promise
包从他们的 URL(s) 下载图像。由于有大量图像,服务器超载并且下载会挂起或损坏,所以我决定使用 promise-limit
库来设置并发限制。这是我的代码:
const fs = require('fs');
const request = require('request-promise');
const promiseLimit = require('promise-limit');
var limit = promiseLimit(30);
async function download(data) {
console.log(data);
return Promise.all(data.map( (obj) => {
return limit(() => downloadRequest(obj))
})).then(() => {
console.log("All images downloaded.")
})
function downloadRequest(obj) {
var img = obj.dest;
var url = obj.url;
var req = request(url);
req.pipe(fs.createWriteStream(img));
}
我完全按照 github 页面中给出的方法复制了示例,但是方法 returns 从未实现 Promise.all()
。我不明白我做错了什么,我认为 Promise.all() 肯定会等到它解决所有的承诺。
在后端,这个调用被用作
...
.then((data) => {
return downloader.download(data);
})
.then(() => {
var filename = "Sample.pdf";
// Pages.json is written early in the chain, contains URL and corresponding image paths
return generator.generate('./Pages.json', filename);
});
这是否意味着 NodeJS 已经在尝试从 pages.json 中生成文件?如何让这部分代码同步下载?
您的函数 downloadRequest()
没有 return 承诺。它必须 return 包含与异步操作相关联的承诺,以便在异步操作完成时解决承诺,或在异步操作出错时拒绝承诺。只有当它这样做时,limit()
包才能正确地完成它的工作。
由于您正在使用流并将其通过管道传输到 downloadRequest()
,因此您必须手动构建一个承诺,然后监视流中的各种事件以了解它何时完成或出现错误,因此您可以解决或拒绝该承诺。
这里有一个如何downloadRequest()
正确return承诺的想法:
function downloadRequest(obj) {
return new Promise((resolve, reject) => {
const img = obj.dest;
const url = obj.url;
const req = request(url);
req.on('error', reject);
const ws = fs.createWriteStream(img);
ws.on('error', reject);
req.pipe(ws).on('finish', resolve);
});
}
而且,现在建议使用 pipeline()
函数而不是 .pipe()
,因为它在错误情况下会进行更彻底的清理,并且还有一个内置的 promise 版本:
const { pipeline } = require('stream/promises');
function downloadRequest(obj) {
return pipeline(request(obj.url), fs.createWriteStream(obj.dest));
}
P.S。如果您不知道,request()
库已被弃用,建议您不要再在新项目中使用它。在我的工作中有一个可供选择的替代库列表 here, all of which also have built-in promise support. I've looked at the various choices, tried several and decided I'm using got()
。
我有大量图片要下载。我正在使用 request-promise
包从他们的 URL(s) 下载图像。由于有大量图像,服务器超载并且下载会挂起或损坏,所以我决定使用 promise-limit
库来设置并发限制。这是我的代码:
const fs = require('fs');
const request = require('request-promise');
const promiseLimit = require('promise-limit');
var limit = promiseLimit(30);
async function download(data) {
console.log(data);
return Promise.all(data.map( (obj) => {
return limit(() => downloadRequest(obj))
})).then(() => {
console.log("All images downloaded.")
})
function downloadRequest(obj) {
var img = obj.dest;
var url = obj.url;
var req = request(url);
req.pipe(fs.createWriteStream(img));
}
我完全按照 github 页面中给出的方法复制了示例,但是方法 returns 从未实现 Promise.all()
。我不明白我做错了什么,我认为 Promise.all() 肯定会等到它解决所有的承诺。
在后端,这个调用被用作
...
.then((data) => {
return downloader.download(data);
})
.then(() => {
var filename = "Sample.pdf";
// Pages.json is written early in the chain, contains URL and corresponding image paths
return generator.generate('./Pages.json', filename);
});
这是否意味着 NodeJS 已经在尝试从 pages.json 中生成文件?如何让这部分代码同步下载?
您的函数 downloadRequest()
没有 return 承诺。它必须 return 包含与异步操作相关联的承诺,以便在异步操作完成时解决承诺,或在异步操作出错时拒绝承诺。只有当它这样做时,limit()
包才能正确地完成它的工作。
由于您正在使用流并将其通过管道传输到 downloadRequest()
,因此您必须手动构建一个承诺,然后监视流中的各种事件以了解它何时完成或出现错误,因此您可以解决或拒绝该承诺。
这里有一个如何downloadRequest()
正确return承诺的想法:
function downloadRequest(obj) {
return new Promise((resolve, reject) => {
const img = obj.dest;
const url = obj.url;
const req = request(url);
req.on('error', reject);
const ws = fs.createWriteStream(img);
ws.on('error', reject);
req.pipe(ws).on('finish', resolve);
});
}
而且,现在建议使用 pipeline()
函数而不是 .pipe()
,因为它在错误情况下会进行更彻底的清理,并且还有一个内置的 promise 版本:
const { pipeline } = require('stream/promises');
function downloadRequest(obj) {
return pipeline(request(obj.url), fs.createWriteStream(obj.dest));
}
P.S。如果您不知道,request()
库已被弃用,建议您不要再在新项目中使用它。在我的工作中有一个可供选择的替代库列表 here, all of which also have built-in promise support. I've looked at the various choices, tried several and decided I'm using got()
。