2014-12-01 4 views
1

비동기 기능을 실행하는 service을 사용하려고합니다. 팩토리를 호출하려고 시도 중입니다. 그런 다음 해결 된 것만 수행하십시오. 하지만 작동하지 않습니다. 오류가 발생합니다. Uncaught TypeError: Cannot read property 'then' of undefined각도, 이온, 서비스 약속, 지연, 비동기

지연된 개체를 서비스 함수로 선언하고 있으며 그 약속을 반환합니다.

제발 도와 주실 수 있습니까?

app.js :

angular.module('SnowBoard', ['ionic', 'ngCookies', 'ui.unique', 'SnowBoard.controllers', 'SnowBoard.services']) 

.run(["isPhoneGap","connectionStatus", 'updateProDB', "$ionicPlatform", '$q', 'sessionService', 'imagesService', function(isPhoneGap, connectionStatus, updateProDB, $ionicPlatform, $q, sessionService, imagesService) { 
    $ionicPlatform.ready(function() { 
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard 
    // for form inputs) 
    if(window.cordova && window.cordova.plugins.Keyboard) { 
     cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true); 
    } 
    if(window.StatusBar) { 
     // org.apache.cordova.statusbar required 
     StatusBar.styleDefault(); 
    } 
    }); 


    var promise = updateProDB.get(); 
    promise.then(
      function(data) { 
       imagesService.checkIfImagesExistAllAtOnce(prodata); 
      }, 
      function(error) { 

      }); 
}]) 

service.js :

.service('updateProDB', ['isPhoneGap', 'connectionStatus', 'isIOS', '$q', 'sessionService', function updateProDBFactory(isPhoneGap, connectionStatus, isIOS, $q, sessionService) { 
    this.get = function(){ 

     var debugOptionUseLocalDB=0; 
     var prodata=[]; 
     var gotANewDB; 
     var dbReadyDeferred = $q.defer(); 

     if (typeof debugOptionUseLocalDB != 'undefined' && debugOptionUseLocalDB) { 
      fallbackToLocalDBfile(); 
      return dbReadyDeferred.promise; 
      gotANewDB = 1; 
      console.log('on a fini fallbackToLocalDBfile, et dbReadyDeferred.state()='+dbReadyDeferred.state()); 
     }else{ 
      if(connectionStatus == 'online'){ 
       console.log("reaching DB on server (getJsonpFile)..."); 

       getDBfileXHR(dbUrl()).then(function(){ //if resolved 
         console.log(prodata); 
         return dbReadyDeferred.promise; 
        }, function(){ // if rejected 
         console.log("...basic XHR request failed, falling back to local DB file...and sending mail to dev."); 
         fallbackToLocalDBfile(); 
         return dbReadyDeferred.promise; 
         var body = ""; 
         if (isPhoneGap) { 
          body += " Platform : phonegap"; 
          body += " device.cordova : "+device.cordova; 
          body += " device.model : "+device.model; 
          body += " device.name : "+device.name; 
          body += " device.platform : "+device.platform; 
          body += " device.uuid : "+device.uuid; 
          body += " device.version : "+device.version; 
         } else { 
          body += "Platform : not phonegap -> web browser" 
          body += "navigator.userAgent : "+navigator.userAgent; 
         } 
         var data={ 
           userEmail: "[email protected]", 
           subject: "BoardLine dev issue: had to fallback to local DB file", 
           destEmail: "[email protected]", 
           body: body   
           } 
         sendToServer(data).done(funcSuccess).fail(funcError); 
         function funcSuccess(data /* , textStatus, jqXHR */) { 
          console.log("Message to dev successfully sent"); 
         } 
         function funcError(data , textStatus, jqXHR ) { 
          console.log("The message to dev could not be sent..."); 
         } 
        }); 


      }else{ //offline 
       console.log('device is offline'); 
       if(localStorage) { 
        if (isPhoneGap || !isIOS()) { //BUG iOS safari doesn't work with this (Cf. Philippe's ipad) 
         if (localStorage.getItem("proDB") === null) { //if proDB exists in localStorage 
          fallbackToLocalDBfile(); 
         } else { 
          //popShortToast("...reading DB in localStorage."); 
          var data = JSON.parse(localStorage["proDB"]); //read current localstorage 
          prodata = storeJsonInProdata(data); 
          sessionService.store('prodata', prodata); 
          dbReadyDeferred.resolve(); //initializeSelectButtons(); 
          return dbReadyDeferred.promise; 
         } 
        } 
       }else{ //if localStorage not available, read local file 
        prodata = fallbackToLocalDBfile(); 
        return dbReadyDeferred.promise; 
       } 
      } 
     } 

     function getDBfileXHR(url) { 
      var getDBfileXHRdeferred = $q.defer(); 
      var request = new XMLHttpRequest(); 
      request.open("GET", url, true); //3rd parameter is sync/async 
      request.timeout = 2000; 
      //console.log(url); 
      request.onreadystatechange = function() {  //Call a function when the state changes. 
       if (request.readyState == 4) { 
        if (request.status == 200 || request.status == 0) { 
        console.log('we get a response from XHR'); 
        //popShortToast("...updating DB from server using simple XHR."); 
        var jsonText = request.responseText.replace("callback(", "").replace(");", ""); 
        prodata = storeJsonInProdata(JSON.parse(jsonText)); 
        sessionService.store('prodata', prodata); 
        // console.log(prodata); 
        gotANewDB = 1; 
        getDBfileXHRdeferred.resolve(); 
        dbReadyDeferred.resolve(); 
        } else { 
        console.log('error : request.status = '+request.status); 
        getDBfileXHRdeferred.reject(); 
        } 
       } 
      } 
      console.log("Sending XMLHttpRequest..."); 
      request.send(); 
      return getDBfileXHRdeferred.promise; 
     } 
     function dbUrl(){ 
      return unescape(encodeURIComponent("http://user:[email protected]/app/proDB.jsonp")); //JSONP 
     } 
     function fallbackToLocalDBfile(){ 
      getDBfileXHR('proDB.jsonp').then(function(){ //if resolved 
         console.log(prodata); 
         return dbReadyDeferred.promise; 
        }); 
     } 
    } 

    function sendToServer(dataToSend) { 
     return $.ajax({ 
      url: 'http://aurel:[email protected]/app/mail.php', 
      type: "POST", 
      dataType: "xml", 
      data: dataToSend 
     }); 
    } 
    function storeJsonInProdata(data) { //function to store the DB json file into a variable prodata usable in the whole app 
     console.log("storing json in prodata"); 
     //clear prodata first 
     var prodata=[]; 
     //if JSON 
     var lines=[]; 
     for(var i = 0; i <= data.length; i++){ 
      lines[i]=data[i]; 
     } 
     var fieldnames=lines[0]; 
     //if tab separated TXT with each model on a separate line 
     //  var lines=data.split(/\n/); 
     //  var fieldnames=lines[0].split(/\t/); 
     var i; 
     prodata.push(lines[0]); 
     //prodata.push(0); 
     for (i = 1; i < lines.length-1; ++i) { 
      //if JSON 
      var fields=lines[i]; 
      //if TXT    
      //   var fields=lines[i].split(/\t/); 
      //prodata.push(i);   
      var j; 
      prodata[i]={}; 
      prodata[i]['id']=i; //auto id, there is no more 'id' column in the DB file. 
      for (j = 0; j < fields.length; ++j) { 
       var str=fieldnames[j]; 
       prodata[i][str]=fields[j]; 
      } 
     } 
     return prodata; 
    } 

}]); 
+0

그 방법은 상당히 있습니다. 모든 길은 약속을 되 돌리는가? 나는 일종의 말할 수 없다. –

+0

(또한 fall-back-to-local 코드에서는'gotANewDB'를 1로 설정하고 실행하지 않고 반환 값을 얻었습니까?) –

+0

(사실,이 오류는 계속해서 반복적으로 발생합니다 (getDBfileXHR' 호출 다음에 코드가 * 많이 * 있습니다.) 한 걸음 뒤로 물러서 코드 검토를 할 수 있습니다. –

답변

1

는 값을 반환하지 않는 적어도 하나 개의 경로로를 표시는, 간단히 말해서 경로 곳이다 :

if (connectionStatus == 'online')도 퇴각하지 않는 것으로 보인다 n 아무것도 즉시.

코드를 따르기가 약간 어려울 수 있습니다. – 위의 내용이 완전히 정확하지 않을 수 있습니다.

해당 지점에서만 fallbackToLocalDBfile()이 호출되며 돌아 오지 않는 것으로 보입니다.

if (typeof debugOptionUseLocalDB != 'undefined' && debugOptionUseLocalDB) { 
    fallbackToLocalDBfile(); 
    gotANewDB = 1; 
    return dbReadyDeferred.promise; 
} else { 
    if (connectionStatus == 'online') { 
    // 
    // !!!!!!!!!! HERE !!!!!!!!!! 
    // 
    getDBfileXHR(dbUrl()).then(function() { 
     console.log(prodata); 
     return dbReadyDeferred.promise; 
    }, function() { 
     fallbackToLocalDBfile(); 

     // The isPhoneGap/etc. and sendToServer() call; elided for clarity 
     sendDevMessage(); 

     return dbReadyDeferred.promise; 
    }); 
    } else { 
    if (localStorage) { 
     if (isPhoneGap || !isIOS()) { //BUG iOS safari doesn't work with this (Cf. Philippe's ipad) 
     if (localStorage.getItem("proDB") === null) { 
      // 
      // !!!!!!!!!! HERE !!!!!!!!!! 
      // 
      fallbackToLocalDBfile(); 
     } else { 
      var data = JSON.parse(localStorage["proDB"]); 
      prodata = storeJsonInProdata(data); 
      sessionService.store('prodata', prodata); 
      dbReadyDeferred.resolve(); 
      return dbReadyDeferred.promise; 
     } 
     } 
    } else { 
     prodata = fallbackToLocalDBfile(); 
     return dbReadyDeferred.promise; 
    } 
    } 
} 

오류가 어려운 더 도움하게 발생하는 아래의 상황을 설명하지 (나는. 생각 ), 그러나 당신이 다시 undefined을 얻을되는 조건 중 적어도 하나 개의 세트가있다 표시하고 may 내가 여기에서 강조하고있는 하나 일 수있다.

다시 말해서 어둠 속에서 다소 찌르는 것입니다. AngularJS, jQuery (AFAICT, 다시 : $.ajax 호출), raw XMLHttpRequests 등을 혼합하여 코드를 이해하기가 어렵습니다. 최소한 어려운 일에 대해 추론하는 현저한 숫자의 문제가 있습니다.

+0

좋아요! @DaveNewton 대단히 감사하고 내 지저분한 코드에 대해 사과드립니다. 나는 당신의 권고에 따라 그것을 깨끗이하려고 노력할 것입니다. – Louis

+0

@ 루이스 It'a 확실히 과정 - 모든 것을 파악하는 데 시간이 걸립니다. 전체 애플리케이션을 한번에 변환하려고 시도하는 대신 한 번에 하나씩 작은 단계를 거치며 JS 코드를 평평하게하여 "피라미드의 운명"을 피하고 더 작은 부분을 추가하기 전에 작동하도록하십시오. 혼란스러운 코드를 한꺼번에 사용하려고 시도하는 것은 고통의 처방입니다. –

+0

이 조언을 주셔서 감사합니다! – Louis

0

루이, 가능한 모든 지점에서 무엇인가가 반환되는지 확인하는 것이 더 있습니다.

.get()은 궁극적으로 prodata의 약속을 반환하지만 각 내부 함수에서 반환 할 내용을 정확히 알아야합니다.

dbReadyDeferredgetDBfileXHRdeferred이라는 명시적인 약속을하지 않아도 모든 작업을 수행 할 수 있고해야합니다. 이들은 불필요하며 많은 return dbReadyDeferred.promise 문이 잘못되었습니다.

각진 환경에서는 jQuery.ajax()을 사용하여 약간의 어색함이 생깁니다. "적절한"해결책은 jQuery.ajax() 대신 $http()을 사용하는 것이지만, $ q로 jQuery 약속을 강요하여 많은 것을 달성 (또는 적어도 시도)하면 .get()은 항상 angualr 약속을 보장합니다.

서비스가 많이 수정 된이 버전은 테스트되지 않았으므로 아직 디버깅해야하지만 필요한 사항을 파악해야합니다.

.service('updateProDB', ['isPhoneGap', 'connectionStatus', 'isIOS', '$q', 'sessionService', function updateProDBFactory(isPhoneGap, connectionStatus, isIOS, $q, sessionService) { 
    this.get = function() { 
     var debugOptionUseLocalDB = 0; 
     if(typeof debugOptionUseLocalDB != 'undefined' && debugOptionUseLocalDB) { 
      return fallbackToLocalDBfile(); 
     } else { 
      if(connectionStatus == 'online') { 
       console.log("reaching DB on server (getJsonpFile)..."); 
       return getDBfileXHR(dbUrl()).then(null, function() { 
        console.log("...basic XHR request failed, falling back to local DB file...and sending mail to dev."); 
        return fallbackToLocalDBfile().then(function(prodata) { 
         var body = []; 
         if (isPhoneGap) { 
          body.push("Platform : phonegap"); 
          body.push("device.cordova : " + device.cordova); 
          body.push("device.model : " + device.model); 
          body.push("device.name : " + device.name); 
          body.push("device.platform : " + device.platform); 
          body.push("device.uuid : " + device.uuid); 
          body.push("device.version : " + device.version); 
         } else { 
          body.push("Platform : not phonegap -> web browser"); 
          body.push("navigator.userAgent : " + navigator.userAgent); 
         } 
         var data = { 
          userEmail: "[email protected]", 
          subject: "BoardLine dev issue: had to fallback to local DB file", 
          destEmail: "[email protected]", 
          body: body.join(' ') 
         }; 
         return sendToServer(data).then(function() { 
          return prodata; 
         }, function(textStatus) { 
          console.error("The message to dev could not be sent... :" + textStatus); 
          return textStatus; 
         }); 
        }); 
       }); 
      } else { //offline 
       console.log('device is offline'); 
       if(localStorage) { 
        if (isPhoneGap || !isIOS()) { //BUG iOS safari doesn't work with this (Cf. Philippe's ipad) 
         if (localStorage.getItem("proDB") === null) { //if proDB doesn't exist in localStorage 
          return fallbackToLocalDBfile(); 
         } else { 
          var data = JSON.parse(localStorage["proDB"]); //read current localstorage 
          var prodata = storeJsonInProdata(data); 
          sessionService.store('prodata', prodata); 
          return $q.when(prodata); //promise of prodata 
         } 
        } else { 
         return fallbackToLocalDBfile(); 
        } 
       } else { //if localStorage not available, read local file 
        return fallbackToLocalDBfile(); 
       } 
      } 
     } 
     function getDBfileXHR(url) { 
      console.log("Sending XMLHttpRequest..."); 
      var jqXHR = $.ajax({ 
       url: url, 
       dataType: 'json', 
       timeout: 2000 
      }).then(function(data) { 
       var prodata = storeJsonInProdata(data); 
       sessionService.store('prodata', prodata); 
       return prodata; 
      }, function(jqXHR, textstatus, errorThrown) { 
       console.error('getDBfileXHR: url=' + url + ': ' + textstatus); 
       return textstatus; 
      }); 
      return $q.when(jqXHR);//coerce jQuery promise to angular 
     } 
     function dbUrl() { 
      return unescape(encodeURIComponent("http://user:[email protected]/app/proDB.jsonp")); //JSONP 
     } 
     function fallbackToLocalDBfile() { 
      return getDBfileXHR('proDB.jsonp'); 
     } 
    } 

    function sendToServer(dataToSend) { 
     var jqXHR = $.ajax({ 
      url: 'http://aurel:[email protected]/app/mail.php', 
      type: "POST", 
      dataType: "xml", 
      data: dataToSend 
     }).then(function(data, textStatus, jqXHR) { 
      return data; 
     }, function(jqXHR, textStatus, errorThrown) { 
      console.error('sendToServer: dataToSend=' + dataToSend + ': ' + textstatus); 
      return textStatus; 
     }); 
     return $q.when(jqXHR);//coerce jQuery promise to angular 
    } 
    function storeJsonInProdata(lines) { //function to store the DB json file into a variable prodata usable in the whole app 
     var i, j; 
     console.log("storing json in prodata"); 
     var prodata = [lines[0]]; 
     for (i = 1; i < lines.length-1; ++i) { 
      prodata[i] = { 'id': i }; //auto id, there is no more 'id' column in the DB file. 
      for (j = 0; j < lines[i].length; ++j) { 
       prodata[i][lines[0][j]] = lines[i][j]; 
      } 
     } 
     return prodata; 
    } 
}]); 

나는 문제의 코드와 같은 전체 구조와 함께 붙어했지만 당신은 (그리고 어쩌면한다)을 중앙에 이러한 오류를 호출 될 때마다 점 fallbackToLocalDBfile(prodata)에서 오류를 던지고 처리하여 일을 더 소요될 수 있습니다 일반화 된 catch. 그것은 더 깨끗합니다.

나는 또한 시험을 필요로 할 storeJsonInProdata()을 정돈하려고 시도했다.