简体   繁体   English

使用来自bluebird的request.getAsync,如何“管道”到文件

[英]Using request.getAsync from bluebird, how to 'pipe' to a file

I'm trying to get the content of some pdf's file asynchronously. 我正在尝试异步获取某些pdf文件的内容。 To do that I'm using Promise.mapSeries with request.getAsync and spread from bluebird . 为此,我将Promise.mapSeriesrequest.getAsync Promise.mapSeries使用并从bluebird spread

But in the then I need to get the result of that request using pipe and createWriteStream directly. 但是在then我需要直接使用pipecreateWriteStream获得该request的结果。 Something like: 就像是:

request(url).pipe(fs.createWriteStream(file));

This is the code, I'm using: 这是代码,我正在使用:

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);
})

My question: 我的问题:

How can I pipe to a file the result from getAsync using the pipe function ? 如何使用pipe功能将getAsync的结果管道传输到文件? It is possible? 有可能的?

PD: I know that I can use fs.promises , but just want to know if it's possible to do it in the way I'm posting PD:我知道我可以使用fs.promises ,但只想知道是否可以用我发布的方式来做

I think the answer is already in the question in that .then() seems to be the .pipe() you seek. 我想答案是已经在这个问题.then()似乎是.pipe()你所追求的。

What's possibly missing is that (result) should be (results) , ie. 可能缺少的是(result)应该是(results) ,即。 an array of all the {name, content} pairs arising from Promise.mapSeries(urls, ...) . 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);
});

In practice you would probably not choose to write it that way because every getAsync() would need to complete before any of the writes commenced. 实际上,您可能不会选择以这种方式编写它,因为每个getAsync()都需要在任何写入开始之前完成。

A better flow under most circumstances (and probably the one you want) would be for content from each successful getAsync() to be written as soon as possible : 在大多数情况下(可能是您想要的情况),更好的流程是尽快将每个成功的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);
});

Going further, you might choose to handle errors better, for example you may wish to : 更进一步,您可能选择更好地处理错误,例如,您可能希望:

  • catch individual url/get/write errors 捕获单个url / get / write错误
  • compile success/failure stats. 编译成功/失败统计信息。

Something like this maybe : 可能是这样的:

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
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM