Sto scrivendo un'app PhoneGap/Cordova con Ionic e utilizzando SQLite (con ngCordova) per l'archiviazione permanente. Il nucleo dell'app è un elenco a scorrimento di elementi che vengono recuperati dal database SQLite.SQLite angolare/ionico e asincrono - garanzia dell'inizializzazione dei dati dei dati prima della restituzione
listController.js
.controller('ListCtrl', [
'$scope',
'dataFactory',
function($scope, dataFactory) {
var items = dataFactory.getAllItems().then(function(data){
$scope.allItems = data;
});
}
]);
dataFactory.js
.factory('dataFactory', [function($window, $log, $q, $cordovaSQLite, dummyDataGenerator){
var db_;
// ...lots of SQLite fun in here
// cascading async callbacks to load the database and inject dummy data
var openDB_ = function(){...};
var createTable_ = function(){...};
// etc
var getAllItems = function(){
var q = $q.defer();
$cordovaSQLite.execute(db_, sqlSelectString, []).then(
function(results) {
$log.log("SQL SELECT successful");
var i, len, allItems = [];
for(i = 0, len = results.rows.length; i < len; i++) {
allItems.push(results.rows.item(i));
}
q.resolve(allItems);
},
function (err) {
q.reject(err);
}
);
return q.promise;
};
return { getAllItems: getAllItems };
]}); // <-- factory
Inizialmente stavo tornando alla fabbrica subito. Il controller eseguiva getAllItems()
che veniva eseguito prima che i dati fossero pronti. La vista era inizialmente vuota, mostrando solo qualcosa al ritorno sulla rotta dopo un secondo getAllItems()
Così ho provato a ritardare il ritorno della fabbrica aggiungendo una funzione factoryReady() e chiamandola solo una volta che tutta la roba DB interna era pronta
var factoryReady = function(){
return {
getAllItems: getAllItems
};
};
E ora c'è un errore non definito come l'intero fabbrica non è disponibile con il primo richiamo, piuttosto che getAllItems()
semplicemente tornare a mani vuote. Posso vedere che il database SQL è stato scritto correttamente a tempo debito, ma Angular lancia un'eccezione prima che questo sia finito.
Mi rendo conto ora che questo è prevedibile, ho letto il post AngularJS : Initialize service with asynchronous data, ma non capisco come implementare la soluzione top-ranked (da joakimbl)
Qual è il modo migliore per esporre il servizio e assicurati che non venga chiamato dal controller fino a quando le cose asincrone interne non saranno terminate? Devo restituire il SERVIZIO INTERO come una promessa anziché solo il risultato di getAllItems
? Ho provato a farlo ma ora sono confuso. Grazie.
EDIT
Ho anche guardato in utilizzando del resolve
quando si carica la vista http://blog.brunoscopelliti.com/show-route-only-after-all-promises-are-resolved ma che non risolve la disponibilità interna del SQL data/factory ui-router. Se restituisco il metodo getAllCases
, viene comunque chiamato immediatamente, non c'è ancora nulla nel database SQL, la query SQL restituisce un set di risultati vuoto, la promessa viene risolta e la vista viene renderizzata.