2015-10-16 2 views
0

Мне нужно выполнить некоторые шаги в моем контроллере (при загрузке). Я хочу выбрать данные в локальной базе данных SQLite, а если не существует, выполните запрос в моем веб-сервисе. Все это с индикатором загрузки. Я использую Ionic Framework и AngularJS.Выполнять шаги с использованием ionicLoading и AngularJS

Мой фактический код не показывает прогресс и инвертирует порядок получения данных (Funcionarios before Empresas).

Контроллер:

$scope.$on('$ionicView.loaded', function() { 
    $ionicLoading.show({ 
     template: 'loading' 
    }) 

    //search in local database 
    RepositorioEmpresas.obterTodos().then(function (empresas) { 
     $scope.empresas = empresas;   

     if ($scope.empresas.length == 0) { 
      //request to webservice 
      ServicoEmpresas.obterEmpresas($rootScope.idSupervisor).then(function (response) { 

       if (response.status == 1) { 
        $scope.empresas = response.dados; 

        //add data retrieve in local database 
        for (var i = 0; i < $scope.empresas.length; i++) { 
         RepositorioEmpresas.adicionar($scope.empresas[i]); 
        }       
       } 
      }, function (e) { 
       Mensagem.alerta('error'); 
       $ionicLoading.hide(); 
      }); 
     } 

     $rootScope.empresas = $scope.empresas; 
    }); 

    //similar to the previous 
    RepositorioFuncionarios.obterTodos().then(function (funcionarios) { 
     var funcionariosTemp = funcionarios;    

     if (funcionariosTemp.length == 0) { 
      ServicoFuncionarios.obterFuncionarios($rootScope.idSupervisor).then(function (response) { 

       if (response.status == 1) { 
        funcionariosTemp = response.dados; 

        RepositorioFuncionarios.removerTodos(); 

        for (var i = 0; i < funcionariosTemp.length; i++) { 
         RepositorioFuncionarios.adicionar(funcionariosTemp[i]); 
        }      
       } 
      }, function (e) { 
       Mensagem.alerta('error.'); 
       $ionicLoading.hide(); 
      }); 
     }   
    });      

    $ionicLoading.hide(); 
}) 

Услуги

.factory('ServicoFuncionarios', function ($http, $q) { 
    const url = 'url'; 
    var self = this; 
    var retorno = []; 

    self.obterFuncionarios = function (idSupervisor) { 
     var q = $q.defer(); 

     $http.get(url + '&idSupervisor=' + idSupervisor, { timeout: 5000 }) 
      .success(function (resposta) { 
       q.resolve(resposta); 
      }) 
      .error(function (e) { 
       q.reject('erro na consulta ao webservice' + e); 
      }); 

     return q.promise; 
    } 

    return self; 
}) 

.factory('RepositorioFuncionarios', function (Repositorio) { 
    var self = this; 

    self.obterTodos = function() { 
     return Repositorio.query("SELECT id, idEmpresa, nome, cpf FROM funcionarios") 
      .then(function (resultado) { 
       return Repositorio.obterTodos(resultado) 
      }); 
    } 

    self.adicionar = function (funcionario) { 
     var campos = [funcionario.id, funcionario.idEmpresa, funcionario.nome, funcionario.cpf]; 
     return Repositorio.query("INSERT INTO funcionarios (id, idEmpresa, nome, cpf) VALUES (?,?,?,?)", campos); 
    } 

    self.removerTodos = function() { 
     return Repositorio.query("DELETE FROM funcionarios"); 
    } 

    return self; 
}) 

Код обновлен

После отличный ответ, я настроил код. Теперь мне нужно выполнить ServicoEmpresas и ServicoFuncionarios, только если RepositorioEmpresas и RepositorioFuncionarios не возвращают данные (в некоторых случаях HTTP-запрос не требуется). Как я могу контролировать условные обещания?

$ionicLoading.show({ 
     content: 'Atualizando lista de usuários', 
     animation: 'fade-in', 
     showBackdrop: true, 
     maxWidth: 200, 
     showDelay: 0 
    }) 

    RepositorioEmpresas.obterTodos().then(function (empresas) { 
     $scope.empresas = empresas; 
     console.log('Empresas carregadas!'); 

     if ($scope.empresas.length == 0) { 
      return ServicoEmpresas.obterEmpresas($rootScope.idSupervisor) 
     } 

     $rootScope.empresas = $scope.empresas; 
    }).then(function (response) { 
     if (response.status == 1) { 
      $scope.empresas = response.dados; 

      RepositorioEmpresas.removerTodos(); 

      for (var i = 0; i < $scope.empresas.length; i++) { 
       RepositorioEmpresas.adicionar($scope.empresas[i]); 
      } 
      console.log('Empresas consultadas!'); 

      $rootScope.empresas = $scope.empresas; 
     } 
    }).then(function() { 
     return RepositorioFuncionarios.obterTodos(); 
    }).then(function (funcionarios) { 
     var funcionariosTemp = funcionarios; 
     console.log('Funcionários carregados!'); 

     if (funcionariosTemp.length == 0) { 
      return ServicoFuncionarios.obterFuncionarios($rootScope.idSupervisor); 
     } 
    }).then(function (response) { 
     if (response.status == 1) { 
      funcionariosTemp = response.dados; 

      RepositorioFuncionarios.removerTodos(); 

      for (var i = 0; i < funcionariosTemp.length; i++) { 
       RepositorioFuncionarios.adicionar(funcionariosTemp[i]); 
      } 
      console.log('Funcionários consultados!'); 
     } 
    }).catch(function (e) { 
     Mensagem.alerta('Falha na consulta dos dados.'); 
    }).finally(function() { 
     $ionicLoading.hide(); 
    }) 

ответ

0

Вы не chaining 2 обещания.
Они разрешаются независимо, поэтому у вас нет гарантий, на которых выполняется другая.

Служба $http уже возвращает обещание, чтобы вы могли избежать этого:

var q = $q.defer(); 

$http.get(url + '&idSupervisor=' + idSupervisor, { timeout: 5000 }) 
     .success(function (resposta) { 
     q.resolve(resposta); 
    }) 
    .error(function (e) { 
     q.reject('erro na consulta ao webservice' + e); 
    }); 

return q.promise; 

а просто:

return $http.get(url + '&idSupervisor=' + idSupervisor, { timeout: 5000 }); 

$ Q обещает прикованы с помощью .then() если они resolved или .catch() если есть ошибка.

Ваш код должен сделать что-то вроде этого:

RepositorioEmpresas.obterTodos() 
    .then(function (empresas) { 
     return ServicoEmpresas.obterEmpresas($rootScope.idSupervisor); 
    }) 
    .then(function (response) { 
     if (response.status == 1) { 
      $scope.empresas = response.dados; 

      //add data retrieve in local database 
      for (var i = 0; i < $scope.empresas.length; i++) { 
       RepositorioEmpresas.adicionar($scope.empresas[i]); 
      }       
       }  
    }) 
    .then(function(){ 
     return RepositorioFuncionarios.obterTodos(); 
    }) 
    .then(function (funcionarios){ 

    }) 
    .catch(function(reason() { 
     // reason contains your error. 
    }); 

Как вы можете видеть в каждом .then() мы называем функцию/метод, который решает обещание и использовать возвращение, чтобы мы могли использоваться возвращенное значение (если обещание решительность) к следующему .then():

.then(function (empresas) { 
    return ServicoEmpresas.obterEmpresas($rootScope.idSupervisor); 
}) 
.then(function (response) { 
    // response is the returned value of ServicoEmpresas.obterEmpresas 
}) 

, как вы сделали вещи вызывает проблемы с $ionicLoading службы, а также, так как вы звоните $ionicLoading.hide(); в самом низу. Эта команда будет выполняться непосредственно перед выполнением обещаний, которые будут разрешены, если служба $http возвращает результат.

Вы можете использовать .finally() сделать некоторые очистке:

myPromise() 
    .then(function (result) { 
     return myOtherPromise(); 
    }) 
    .then(function (result) { 
     // do something with the final result. 
    }) 
    .catch(function (reason) { 
     // reason contains your error. 
    }) 
    .finally(function(){ 
     $ionicLoading.hide(); 
    }); 

Другой вариант заключается в использовании перехватчиков:

app.config(function($httpProvider) { 
    $httpProvider.interceptors.push(function($rootScope) { 
    return { 
     request: function(config) { 
     $rootScope.$broadcast('loading:show') 
     return config 
     }, 
     response: function(response) { 
     $rootScope.$broadcast('loading:hide') 
     return response 
     } 
    } 
    }) 
}) 

, которые будут вызывать события и события сами будут перехвачены в $rootScope:

app.run(function($rootScope, $ionicLoading) { 
    $rootScope.$on('loading:show', function() { 
    $ionicLoading.show({template: 'foo'}) 
    }) 

    $rootScope.$on('loading:hide', function() { 
    $ionicLoading.hide() 
    }) 
}) 

таким образом у вас есть мана чтобы показать/скрыть индикатор загрузки каждый раз, когда выполняется длинный HTTP-запрос.

Пояснение here.

+0

Отличный ответ! Вы решили все мои сомнения по этому поводу. Большое спасибо! У меня есть только вопрос об условных обещаниях (я обновил вопрос). –

+0

Вы можете проверить возвращенные данные. Если нет данных, вы можете просто «вернуть true» или «return;», и цепочка перейдет к следующей ветке. Как только вы попадете в цепочку, вы можете вернуть синхронизацию или результат async (обещание), и цепь будет соблюдаться. Существует [статья] (http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html), которую я считаю лучшим по обещаниям - что стоит прочитать. С самого начала трудно понять, но через некоторое время все ясно. Посмотрите на ** Ошибка новичков # 5 **. Приветствия. – LeftyX

+0

Не забудьте принять ответ, если вы довольны этим. Благодарю. – LeftyX

Смежные вопросы