使用 bluebird 的 request.getAsync,如何 'pipe' 到一个文件
Using request.getAsync from bluebird, how to 'pipe' to a file
我正在尝试异步获取某些 pdf 文件的内容。为此,我将 Promise.mapSeries
与 request.getAsync
和 spread
来自 bluebird.
但在 then
中,我需要直接使用 pipe
和 createWriteStream
获得 request
的结果。类似于:
request(url).pipe(fs.createWriteStream(file));
这是代码,我正在使用:
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'), { multiArgs: true });
const fs = Promise.promisifyAll(require("fs"));
const urls = ['http://localhost/test-pdf/one.pdf', 'http://localhost/test-pdf/two.pdf'];
Promise.mapSeries(urls, url => {
return request.getAsync({url: url, encoding:'binary'}).spread((response, body) => {
if (response.statusCode == 200){
let r = {};
r.name = url.match(/\/([^/]*)$/)[1]; // get the last part of url (file name)
r.content = body;
console.log(`Getting ${r.name}`);
return r;
}
else if (response.statusCode == 404){
console.log(`The archive ${url.match(/\/([^/]*)$/)[1]} does not exists`);
}
else throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
});
}).then((result) => {
// Here I want to 'pipe' to a file the result from 'getAsync'
}).catch((error) =>{
console.error(error);
})
我的问题:
如何使用 pipe
函数将 getAsync
的结果 管道 到文件?有可能吗?
PD: 我知道我可以使用 fs.promises
,但只是想知道是否可以按照我发布的方式使用 [=24] =]
我认为答案已经在问题中,因为 .then()
似乎是您要寻找的 .pipe()
。
可能缺少的是 (result)
应该是 (results)
,即。来自 Promise.mapSeries(urls, ...)
.
的所有 {name, content}
对的数组
Promise.mapSeries(urls, url => {
return request.getAsync({'url':url, 'encoding':'binary'}).spread((response, body) => {
if (response.statusCode == 200) {
return {
'name': url.match(/\/([^/]*)$/)[1], // get the last part of url (file name)
'content': body
};
} else if (response.statusCode == 404) {
throw new Error(`The archive ${url.match(/\/([^/]*)$/)[1]} does not exist`);
} else {
throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
}
});
}).then((results) => {
// Here write each `result.content` to file.
}).catch((error) => {
console.error(error);
});
实际上你可能不会选择那样写,因为每个 getAsync()
都需要在任何写入开始之前完成。
在大多数情况下(也可能是您想要的)更好的流程是尽快编写每个成功 getAsync()
的内容:
Promise.mapSeries(urls, url => {
let name = url.match(/\/([^/]*)$/)[1]; // get the last part of url (file name)
return request.getAsync({'url':url, 'encoding':'binary'}).spread((response, body) => {
if (response.statusCode == 200) {
// write `body.content` to file.
} else if (response.statusCode == 404) {
throw new Error(`The archive ${name} does not exist`);
} else {
throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
}
});
}).catch((error) => {
console.error(error);
});
更进一步,您可能会选择更好地处理错误,例如您可能希望:
- 捕捉个别 url/get/write 错误
- 编译 success/failure 统计数据。
可能是这样的:
Promise.mapSeries(urls, url => {
let name = url.match(/\/([^/]*)$/)[1] || ''; // get the last part of url (file name)
if(!name) {
throw new RangeError(`Error in input data for ${url}`);
}
return request.getAsync({'url':url, 'encoding':'binary'}).spread((response, body) => {
if (response.statusCode == 200) {
// write `body.content` to file.
return { name, 'content': body };
} else if (response.statusCode == 404) {
throw new Error(`The archive ${name} does not exist`);
} else {
throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
}
})
.catch(error => ({ name, error }));
}).then((results) => {
let successes = results.filter(res => !res.error).length;
let failures = results.filter(res => !!res.error).length;
let total = results.length;
console.log({ successes, failures, total }); // log success/failure stats
}).catch((error) => {
console.error(error); // just in case some otherwise uncaught error slips through
});
我正在尝试异步获取某些 pdf 文件的内容。为此,我将 Promise.mapSeries
与 request.getAsync
和 spread
来自 bluebird.
但在 then
中,我需要直接使用 pipe
和 createWriteStream
获得 request
的结果。类似于:
request(url).pipe(fs.createWriteStream(file));
这是代码,我正在使用:
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'), { multiArgs: true });
const fs = Promise.promisifyAll(require("fs"));
const urls = ['http://localhost/test-pdf/one.pdf', 'http://localhost/test-pdf/two.pdf'];
Promise.mapSeries(urls, url => {
return request.getAsync({url: url, encoding:'binary'}).spread((response, body) => {
if (response.statusCode == 200){
let r = {};
r.name = url.match(/\/([^/]*)$/)[1]; // get the last part of url (file name)
r.content = body;
console.log(`Getting ${r.name}`);
return r;
}
else if (response.statusCode == 404){
console.log(`The archive ${url.match(/\/([^/]*)$/)[1]} does not exists`);
}
else throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
});
}).then((result) => {
// Here I want to 'pipe' to a file the result from 'getAsync'
}).catch((error) =>{
console.error(error);
})
我的问题:
如何使用 pipe
函数将 getAsync
的结果 管道 到文件?有可能吗?
PD: 我知道我可以使用 fs.promises
,但只是想知道是否可以按照我发布的方式使用 [=24] =]
我认为答案已经在问题中,因为 .then()
似乎是您要寻找的 .pipe()
。
可能缺少的是 (result)
应该是 (results)
,即。来自 Promise.mapSeries(urls, ...)
.
{name, content}
对的数组
Promise.mapSeries(urls, url => {
return request.getAsync({'url':url, 'encoding':'binary'}).spread((response, body) => {
if (response.statusCode == 200) {
return {
'name': url.match(/\/([^/]*)$/)[1], // get the last part of url (file name)
'content': body
};
} else if (response.statusCode == 404) {
throw new Error(`The archive ${url.match(/\/([^/]*)$/)[1]} does not exist`);
} else {
throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
}
});
}).then((results) => {
// Here write each `result.content` to file.
}).catch((error) => {
console.error(error);
});
实际上你可能不会选择那样写,因为每个 getAsync()
都需要在任何写入开始之前完成。
在大多数情况下(也可能是您想要的)更好的流程是尽快编写每个成功 getAsync()
的内容:
Promise.mapSeries(urls, url => {
let name = url.match(/\/([^/]*)$/)[1]; // get the last part of url (file name)
return request.getAsync({'url':url, 'encoding':'binary'}).spread((response, body) => {
if (response.statusCode == 200) {
// write `body.content` to file.
} else if (response.statusCode == 404) {
throw new Error(`The archive ${name} does not exist`);
} else {
throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
}
});
}).catch((error) => {
console.error(error);
});
更进一步,您可能会选择更好地处理错误,例如您可能希望:
- 捕捉个别 url/get/write 错误
- 编译 success/failure 统计数据。
可能是这样的:
Promise.mapSeries(urls, url => {
let name = url.match(/\/([^/]*)$/)[1] || ''; // get the last part of url (file name)
if(!name) {
throw new RangeError(`Error in input data for ${url}`);
}
return request.getAsync({'url':url, 'encoding':'binary'}).spread((response, body) => {
if (response.statusCode == 200) {
// write `body.content` to file.
return { name, 'content': body };
} else if (response.statusCode == 404) {
throw new Error(`The archive ${name} does not exist`);
} else {
throw new Error(`Unsuccessful attempt. Code: ${response.statusCode}`);
}
})
.catch(error => ({ name, error }));
}).then((results) => {
let successes = results.filter(res => !res.error).length;
let failures = results.filter(res => !!res.error).length;
let total = results.length;
console.log({ successes, failures, total }); // log success/failure stats
}).catch((error) => {
console.error(error); // just in case some otherwise uncaught error slips through
});