2017-03-27 13 views
1

これは簡単な問題だと申し訳ありませんが、数日前にジャンプしてしまいました。コールバックが完了する前にJavaScriptの結果が発生する

私の元の機能は、単に画像をダウンロードして、保存されたカウントを1だけインクリメントしてファイルサイズを追加することでした。しかし、画像のページでは、クロムの書き込み限界に達したので、値を数えて最後に書き込むことにしました。

最初に戻り値は関数が実行されたときよりもずっと遅れていたので(何も返されなかった)、それを修正する方法を調べて、コールバックで動作させました。それは、コールバックを待ちものの、コードは単にコールバックを過ぎて継続され、一部はその後、私はちょうどそのにループを移動しようとした最後のカウントは常に0

// Loop through all urls 
    var approx_filesize = 0; 
    for(var i = 1; i < all_urls.length; i++){ 
     var image_url = all_urls[i]; 
     _download_image(image_url, folder_name, function(item){ 
      approx_filesize += parseInt(item); 
     }); 
    } 

    // This happens before any _download_image functions complete 
    alert('end' + approx_filesize); 

    // Write to storage 
    chrome.storage.sync.get({ 
     download_count: 0, 
     download_size: 0 
    }, function(items) { 
     chrome.storage.sync.set({ 
      download_count: parseInt(items.download_count) + all_images_data.length - 1, 
      download_size: parseInt(items.download_size) + approx_filesize 
     }, function() { 
     }); 
    }); 

なります意味、何か他のものの前に実行されます独自のコールバック関数を使用していて運がまったくない場合、最初の関数が完了する前に警告が実行されます。

function image_url_loop_callback(callback, folder_name, all_urls){ 

    var approx_filesize = 0; 
    for(var i = 1; i < all_urls.length; i++){ 
     var image_url = all_urls[i]; 

     _download_image(image_url, folder_name, function(filesize){ 
      approx_filesize += parseInt(filesize); 
     }); 
    } 
    callback(approx_filesize); 
} 

image_url_loop_callback(function(approx_filesize){ 
    alert(approx_filesize); 
}, folder_name, all_urls); 

何か他のことが行われる前にループが完了するようにするにはどうすればよいですか?

編集:

new Promise(function(resolve, reject) { 
    var count = 1; 
    var num_items = all_urls.length; 
    var approx_filesize = 0; 
    for(var i = 1; i < num_items; i++){ 
     var image_url = all_urls[i]; 

     _download_image(image_url, folder_name, function(item){ 
      approx_filesize += parseInt(item); 
      count ++; 
      if(count == num_items){ 
       resolve([num_items, approx_filesize]); 
      } 
     }); 
    } 
}).then(function(stuff) { 
    var num_items = stuff[0]; 
    var approx_filesize = stuff[1]; 
    chrome.storage.sync.get({ 
     download_count: 0, 
     download_size: 0 
    }, function(items) { 
     chrome.storage.sync.set({ 
      download_count: parseInt(items.download_count) + num_items, 
      download_size: parseInt(items.download_size) + approx_filesize 
     }, function() { 
     }); 
    }); 
}); 

答えて

3

を、あなたが処理する必要がありますJavaScriptの非同期性

これを行うには、Promiseを使用する必要があります。

これは、このように動作します:通常の約束よりもはるかに簡単に非同期処理を行うキーワード(あなたのブラウザの最新バージョンのみを使用している場合、あなたはまた、非同期で見ることができ/待つ

new Promise(() => { 

    // My asynchronous code 

}).then(() => { 

    // My code which need to wait for the promise resolution. 

}); 

が、まだ約束です)。

EDIT:この回答には詳細な説明と適切なコードスニペットが必要でしたので、私はコメントに答えるために編集しました。

この例で多分簡単には理解する:

let myFoo = "Hello"; 

test = new Promise((resolve) => { 

    console.log(myFoo); 

    myFoo = "World!"; 

    setTimeout(() => { 

     resolve(); 

    }, 4000); 

}).then(() => { 

    console.log(myFoo); 

}); 

これは、 "こんにちは"、直ちに、および印刷します "世界を!" 4秒後。

これは、約束事の仕組みです。約束の外のスコープで定義された変数を完全に編集することができます。 varを使わないでください。まともなスコープを定義してください。

+0

おかげさまで、他の人とどうやって使い方を解明しようとしていたのですか? – Peter

+0

微妙な問題 - 私は '約束 'から' then'部分に入る変数が必要です。あなたは 'resolve'を使っているようですが、残りの部分がハハを完了する前に実行されています。変数をどのように取得するのですか? – Peter

+0

私はあなたが遭遇した問題が何であるか分からないので、あなたに適切な例を与えるために私の答えを編集しました。 – SmashingQuasar

関連する問題