2017-05-01 24 views
0

URLからさまざまなファイルを収集し、それらをまとめてzipアーカイブに入れるWebアプリケーションがあります。JS promisiesを関数にラップする

私は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ファイルのバイナリコンテンツを含む約束を返します。 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ファイルを生成すると、私はincudeしようとしているzipファイルの内容を無視します。

私は約束がうまくいかないので、URLを受け取って約束を待っているので、それを通常のzip.fileと一緒に複数回呼び出すことができますジップ生成。ありがとう。

+0

あなたは、あなたの目標が何であるかを明確にすることはできますか?あなたは 'loadAsync'で複数のzipファイルを読み込み、それらを単一のzipにマージしようとしていますか? – nderscore

+0

約束が解決するまで関数が "待つ"ようにしているようです。あなたはJavascriptでそれを行うことはできません。非同期操作を行い、何らかの形でそれを非同期結果を返す同期関数でラップする方法はありません。それはできません。それは頻繁に求められ、それはできません。代わりに、関数から約束を返す適切な非同期コードを書く方法を学び、非同期操作がいつ実行されたかを知るために '.then()'を使い、 '.then() )ハンドラーはあなたのシーケンスの次のステップを開始しますか? – jfriend00

+0

@nderscoreはい、それは私がやろうとしていることです。どのくらいのアーカイブをマージするべきかわかりませんが、ユーザーは余分なアーカイブを追加することはできません。 – mkrl

答えて

1

JSZipUtils.getBinaryContentメソッドをPromiseでラップし、それらの配列を生成できます。次に、Promise.all()を使用して、新しい約定を作成します。これは、配列内のすべての約束が解決されたときに解決されます。

は、ここで私はそれを行うだろうかの例です:

// 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') 
     }) 
}); 
+0

おかげで、私は考えを得ました。しかし、あなたが提出したコードは機能しません、私はここで何が間違っているかを試みます。 – mkrl

+1

@mkrlコードを修正して動作させました。私は自分の答えを更新したし、jsfiddleのデモがある:https://jsfiddle.net/ghvw7brt/ – nderscore

関連する問題