2016-09-16 12 views
0

私は、ユーザーがすべてのツアーは、ユーザーがで遊ぶことができる部品の量を持っている問題が

(データはAPIからである)ツアーを再生することができ、イオンのプロジェクトを構築していますが呼び出されます地図上のある点。このアプリは100%のオフラインアプリでなければならないため、ユーザーがツアーのコードを入力すると、そのデータをAPIから取得してからユーザーが進めるようにする必要があります(ツアーのすべてのデータをオフラインにする)。すべての部分には、アプリの開始時にダウンロードされている画像、ビデオ、オーディオがあります。

問題は、すべてのデータをダウンロードしている関数呼び出しが同期していないことです。 console.logは、すべてのデータがダウンロードされる前に関数がすでに終了していると言っています。以下のコードの断片:

 function getAndFillFullTour() { 
    vm.showLoader = true; 
    // load data 
    TourFactory.getFullTour(vm.tourData.number, function(data){ 
     if(data.state == 'success'){ 
     vm.tourData = data; 
     var test = downloadData(function(){ 
      // hide loader and continue tour 
     }); 
     } else { 
     console.log('error'); 
     } 
    }); 
    } 

この機能は、ユーザーがデバイスにダウンロード取得する必要がある各部分の画像のパスを含む完全なツアーを取得している工場を呼び出します。

function downloadData(callback) { 
    angular.forEach(vm.tourData.parts, function(value, key){ 
     var part = value; 
     var i = key; 

     if(part.image !== "") { 
     TourFactory.getPartImage(part, tourId, function(data){ 
      vm.tourData.parts[i].partImage = data; 
      console.log('executed with picture ' + i); 
     }); 
     } 

    }); 

    if(callback) 
     callback(); 
    } 

残念ながら、forloop自体が同期実行されているが、工場出荷時の呼び出しが完了するのを待っていません:downloadData機能は次の関数です。私は約束をもってたくさんの選択肢を試しましたが、運がありません。誰でも助けてくれますか? downloadData呼び出しからの応答を得るためにhttp呼び出しが完了するのを待つ必要があります。

getPartImage()は単なる例であり、downloadData呼び出しで応答を取得する前に、最初に完了する必要があるループ用の5つの関数があります。

+0

['forEach'は何も待っていません](http://stackoverflow.com/a/37576787/1048572)。 – Bergi

+0

約束を使用しようとしてください。 – Bergi

答えて

1

$q.allまたはhereをご覧ください。これは、複数の約束が完了するのを待つことができる約束ヘルパー機能です。結果は約束ですので、他の約束と連鎖させることができます。

// Promise function that knows how to download a single part 
function downloadPart(myurl) { 
    // return http promise 
    return $http({ 
    method: 'GET', 
    url: myurl 
    }); 
}; 

// Aggregat epromise that downloads all parts 
function downloadAllParts(parts) { 
    var defer = $q.defer(); // Setup return promise 
    var partsPromises = []; // Setup array for indivudual part promises 
    angular.forEach(parts, function(part) { // Iterate through each part 
    // Schedule download of a single 
    partsPromises.push(downloadPart(part)); 
    }); 
    // Wait for all parts to resolve 
    $q.all(partsPromises) 
    .then(function(data) { 
     // Returned data will be an array of results from each individual http promise 
     resData = []; 
     angular.forEach(data, function(partData) { 
     //handle each return part 
     resData.push(partData.data); 
     }) 
     defer.resolve(resData); // Notify client we downloaded all parts 
    }, function error(response) { // Handle possible errors 
     console.log('Error while downloading parts' 
     response); 
     defer.reject('Error while downloading parts'); 
    }); 
    return defer.promise; 
}; 

次に、あなたのクライアントにあなたは、単に完了するのdownloadAllPartsのを待つことができます。$ q.allも同様の約束なので

downloadAllParts(myParts) 
.then(function(data) { 
    alert('Success!'); 
}, function(error) { 
    alert(error); 
}) 

を、あなたはすべて一緒に延期を取り除くことができます。

ここで
// Aggregat epromise that downloads all parts 
function downloadAllParts(parts) { 
    var partsPromises = []; // Setup array for indivudual part promises 
    angular.forEach(parts, function(part) { // Iterate through each part 
    // Schedule download of a single 
    partsPromises.push(downloadPart(part)); 
    }); 
    // Wait for all parts to resolve 
    return $q.all(partsPromises) 
    .then(function(data) { 
     // Returned data will be an array of results from each individual http promise 
     var resData = []; 
     angular.forEach(data, function(partData) { 
     //handle each return part 
     resData.push(partData.data); 
     }) 
     return resData; 
    }); 
}; 

作業jsfiddleです:link

+0

'$ q.defer()'は必要ありません... '$ q.all()'を返すだけですが、 'then()'の中にデータを返すようにしてください – charlietfl

+0

は、それぞれの 'downloadPart( ) '応答オブジェクト – charlietfl

+0

downloadPartはデータを返す約束を返します。したがって、$ q.all約束の 'data'はすべての$ http呼び出しの結果の配列でなければなりません。 – Maksym

0

おかげですべての!次のコードは私のために働いた。私はコメントのソリューションをいくつかのものと統合し、このソリューションは私のために働いていました。

// Aggregat epromise that downloads all parts 
    function downloadAllParts(parts) { 
    vm.showLoader = true; 
    var defer = $q.defer(); // Setup return promise 
    var partsPromises = []; // Setup array for indivudual part promises 
    angular.forEach(parts, function(part, key) { // Iterate through each part 
     // Schedule download of a single 
     if(typeof part.image !== 'undefined' && part.image !== "") { 
     partsPromises.push(downloadPartImage(part)); 
     } 

     if(typeof part.audio !== 'undefined' && part.audio !== "") { 
     partsPromises.push(downloadPartAudio(part)); 
     } 

     if(typeof part.video !== 'undefined' && part.video !== "") { 
     partsPromises.push(downloadPartVideo(part)); 
     } 

     if(key > 0){ 
     vm.tourData.parts[key].available = false; 
     } else { 
     vm.tourData.parts[key].available = true; 
     } 
    }); 
    // Wait for all parts to resolve 
    $q.all(partsPromises) 
     .then(function(data) { 
     // Returned data will be an array of results from each individual http promise 
     resData = []; 
     angular.forEach(data, function(partData) { 
      //handle each return part 
      resData.push(partData); 
     }) 
     defer.resolve(resData); // Notify client we downloaded all parts 
     }, function error(response) { // Handle possible errors 
     console.log('Error while downloading parts' + response); 
     defer.reject('Error while downloading parts'); 
     }); 
    return defer.promise; 
    } 

    function downloadPartImage(part) { 
    var data = { 
     oid: tourId, 
     plid: part.image, 
     func: 'image' 
    }; 

    return TourFactory.getSynchronousPartImage(part, tourId).then(function(data){ 
     part.partImage = data.data; 
     return data; 
    }); 
    }; 

    function downloadPartAudio(part) { 
    var targetPath = cordova.file.externalDataDirectory + tourId + '/audio/' + part._id.$id + '.mp3'; 
    var url = "https://www.tourtodo.com/gameinfo/" + part.audio; 
    var trustHosts = true; 
    var options = {}; 

    return $cordovaFileTransfer.download(url, targetPath, {}, true).then(function (result) { 
     console.log('Save file on '+targetPath+' success!'); 
     part.audioSrc = targetPath; 
     return result; 
    }, function (error) { 
     console.log('Error Download file'); 
     console.log(JSON.stringify(error)); 
     return error; 
    }, function (progress) { 
     console.log((progress.loaded/progress.total) * 100); 
    }); 
    } 

    function downloadPartVideo(part) { 
    var targetPath = cordova.file.externalDataDirectory + tourId + '/video/' + part._id.$id + '.mp4'; 
    var url = "https://www.tourtodo.com/gameinfo/" + part.video; 
    var trustHosts = true; 
    var options = {}; 

    return $cordovaFileTransfer.download(url, targetPath, {}, true).then(function (result) { 
     console.log('Save file on '+targetPath+' success!'); 
     part.videoSrc = targetPath; 
     return result; 
    }, function (error) { 
     console.log('Error Download file'); 
     console.log(JSON.stringify(error)); 
     return error; 
    }, function (progress) { 
     console.log((progress.loaded/progress.total) * 100); 
    }); 
    } 

    function getAndFillFullTour() { 
    vm.showLoader = true; 
    // load data 
    TourFactory.getFullTour(vm.tourData.number, function(data){ 
     if(data.state == 'success'){ 
     vm.tourData = data; 

     downloadAllParts(vm.tourData.parts) 
     .then(function(data) { 
      vm.showLoader = false; 
      vm.showStartButton = true; 
      alertPopup = $ionicPopup.alert({ 
       title: 'Gelukt!', 
       template: 'De tour is opgehaald. Druk op start om de tour te starten.' 
      }); 
      localStorage.setItem('tourdata', JSON.stringify(vm.tourData)); 
      console.log(JSON.parse(localStorage.getItem('tourdata'))); 
     }, function(error) { 
      console.log('error'); 
      console.log(error); 
     }) 
     } else { 
     console.log('error'); 
     } 
    }); 
    } 
+0

Luuk、それはあなたのために働いた場合は、あなた自身のソリューションを受け入れることができます。それ以外の場合は、「開いている質問」キューに問題が残ります。乾杯! – Maksym