将JS promisies包装到函数中

时间:2017-05-01 15:46:38

标签: javascript jquery promise jszip

我有一个Web应用程序,它从URL收集各种文件并将它们放在zip存档中。

我正在使用JSZip来处理zip文件。这是一个代码示例,其中包含位于同一服务器上的另一个zip存档的内容:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>   
   <script type="text/javascript" src="./js/jszip.js"></script>
    <script type="text/javascript" src="./js/jszip-utils.js"></script>
    <script type="text/javascript" src="./js/FileSaver.js"></script>

Downloading archive with contents from another archive



<script>

jQuery(function($) {

            var zip = new JSZip();
            zip.file('see.txt','Regular files are being included with a single function call');



            function flash(){
            JSZipUtils.getBinaryContent('/version.zip', function(err, data) {
                try {
                  zip.loadAsync(data)
                  .then(function(zip) {
                        zip.generateAsync({type: 'blob'},
                        function(metadata) {
                        })
                        .then(function(blob) {
                            saveAs(blob, 'result.zip');

                        }, function(e) {
                            showError(e);
                        });
                  })
                  .then(function success() {

                  });
                } catch(e) {console.log(e)}
              });
            };


        flash();



        return false;

});

</script>

Working JSFiddle with libs and examples included

它运作得很好。 JSZipUtils.getBinaryContent从URL返回带有zip文件二进制内容的promise。 zip.loadAsync()读取二进制内容并将其包含在存档中。 zip.generateAsync在RAM中构建zip存档的表示,以便我们稍后下载。

但是,我需要将zip.loadAsync()包装到一个我可以多次调用的函数中。我尝试过这样的事情:

function zipmerge(source){
JSZipUtils.getBinaryContent(source, function (err, data) {
   if(err) {
      throw err; // or handle the error
   }
   var zip = new JSZip();
   zip.loadAsync(data);
});
};

但看起来zip.loadAsync()需要等待才能完成。如果我只是运行上面的函数,然后生成一个zip文件,它将忽略我试图包含的zip文件的内容。

我对promisies的工作方式不是很了解,所以我需要一个函数的帮助,它会收到一个url并等待承诺解析,所以我可以多次调用它和常规的zip.file和然后触发zip生成。感谢。

1 个答案:

答案 0 :(得分:1)

您可以将JSZipUtils.getBinaryContent方法包装在Promise中并生成它们的数组。然后,您可以使用Promise.all()创建一个新的promise,当数组中的所有promise都已解析时,它将解析。

以下是我将如何做的一个例子:

// function to read in a list of source zip files and return a merged archive
function mergeZips(sources) {
    var zip = new JSZip();

    return readSources(sources, zip)
        .then(function() {
            return zip;
        });
}

// generate an array of promises for each zip we're reading in and combine them
// into a single promise with Promise.all()
function readSources(files, zip) {
    return Promise.all(
        files.map(function(file){
            return readSource(file, zip);
        })
    );
}

// promise-ified wrapper function to read & load a zip
function readSource(file, zip) {
    return new Promise(function(resolve, reject) {
        JSZipUtils.getBinaryContent(file, function (err, data) {
            if (err) {
                reject(err);
            }
            // resolving the promise with another promise will pass the promise
            // down the chain:
            resolve(zip.loadAsync(data)); 
        });
    });
}

// example usage:
mergeZips([
    'file1.zip',
    'file2.zip',
    'file3.zip'
]).then(function(zip) {
    zip.generateAsync({type: 'blob'})
        .then(function(blob){
            saveAs(blob, 'result.zip')
        })
});