使用Promise保存多个文件 [英] Saving multiple files using Promise

查看:126
本文介绍了使用Promise保存多个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个节点URL(使用Express创建),可用于下载地址的静态图像.因此,调用应用程序会调用/download url并使用json传递多个地址,然后下载服务将调用Google Maps并将这些地址的每个静态图像保存在节点服务器上(然后将其发送回调用应用程序,但是出于这个问题的目的,我只想将图像保存在节点服务器中.

I have a Node URL (created using Express) that can be used to download a static image of an address. So, the calling app calls the /download url and passes multiple addresses using json, then the download service would call Google Maps and save the static image of each of these addreses on the node server (it would then send it back to the calling application, but for the purpose of this question I am only interested in saving the images in the node server).

最初,我们只对保存地址的卫星视图感兴趣,所以我编写了这段代码

Initially, we were only interested in saving satellite view of the addresses, so I wrote this code

var request = require('request');
function saveMap(addressJson) {
    return Promise.all(
        //iterate over address json, get each address, call the Google Maps URL and save it.
        addressJson.map(function(item) {
             return new Promise(function (resolve, reject) {
                 var mapUrl = 'http://maps.googleapis.com/maps/api/staticmap?maptype=roadmap&markers=size:mid|color:red|' + item.address;
                 request(mapUrl)
                     .pipe(fs.createWriteStream('/temp/' + item.id + '.jpg'))
                     .on('finish', function () {
                         resolve("Promise resolved");
                     }).on('error', function (error) {
                         reject('Error in creating map', error);
                     })
             });
        })
    )
}

用于保存每个地址的Promise封装在Promise.all(..)中,因为我想在所有地图都完成下载后返回saveMap(),以便我可以将其压缩并发送至调用的应用程序,因此需要确保所有内容均已下载).

The Promise for saving each address is wrapped inside Promise.all(..), since I want to the saveMap() to return when all maps have finished downloading (so that I can zip them and send to the calling app, so need to be sure that everything has been downloaded).

现在,我们需要扩展此功能,使其也包括卫星地图.我希望在同一json迭代中,我可以有另一个Promise,它将下载卫星地图.像这样

Now, we need to extend this function to also include satellite maps. I was hoping, that within same json iteration, I can have another Promise which would download satellite maps. Something like this

function saveMap(addressJson) {
    return Promise.all(
        //iterate over address json, get each address, call the Google Maps URL and save it.
        addressJson.map(function(item) {
             return new Promise(function (resolve, reject) {
                 var mapUrl = 'http://maps.googleapis.com/maps/api/staticmap?maptype=roadmap|' + item.address;
                 request(mapUrl)
                     .pipe(fs.createWriteStream('/temp/r/' + item.id + '.jpg'))
                     .on('finish', function () {
                         resolve("Promise resolved");
                     }).on('error', function (error) {
                         reject('Error in creating map', error);
                     })
             });
             return new Promise(function (resolve, reject) {
                 var mapUrl2 = 'http://maps.googleapis.com/maps/api/staticmap?maptype=satellite|' + item.address;
                 req(mapUrl2)
                     .pipe(fs.createWriteStream(fs.createWriteStream('/temp/s/' + item.id + '.jpg'))
                     .on('finish', function () {
                         resolve("Promised resolved");
                     }).on('error', function (error) {
                         reject('Error in creating map', error);
                     })
             });
        })
    )
}

但是,这无法正常工作.我没有收到错误,但它没有生成所有的jpg文件.有人可以帮我了解我在做什么错以及如何纠正此问题.

However, this does not work as expected. I don't get an error but it is not generating all the jpg files. Can someone please help me understand what I am doing wrong and how to get this corrected.

推荐答案

在该代码中有两个return语句,这就是为什么它不起作用的原因.

You have two return statements in that code which is why it does not work.

但是,您真正应该开始的是提取下载的承诺:

But what you really should start with is to abstract out your promisification of the download:

function download(url, target) {
    return new Promise(function (resolve, reject) {
        request(uUrl).pipe(fs.createWriteStream(target))
        .on('finish', resolve)
        .on('error', reject)
    });
}

现在您可以使用两次.简单起见,我不会尝试只对数组进行一次迭代,而只需map对其进行两次并合并结果.另一种选择是concatMap或对每个项目的承诺进行排序.

Now you can use that twice. For simplicitly, I would not try to iterate your array just once but simply map it twice and concat the results. The alternative would be to concatMap or sequence the promises of each item.

function saveMap(addressJson) {
    var mapUrl = 'http://maps.googleapis.com/maps/api/staticmap?maptype=';
    return Promise.all(addressJson.map(function(item) {
        return download(mapUrl + 'roadmap|' + item.address, '/temp/r/' + item.id + '.jpg');
    }).concat(addressJson.map(function(item) {
        return download(mapUrl + 'satellite|' + item.address, '/temp/s/' + item.id + '.jpg');
    })));
}

这篇关于使用Promise保存多个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆