Reputation: 199
I have multiple INSERTs I'd like to be done before starting SELECT requests. My problem is that the INSERT is not yet finished when the SELECT fires.
Made a factory for the database handling:
databaseFactory.js
factory.insertIntoTable= function (database, data) {
var sqlCommand = 'INSERT INTO blablabla';
database.transaction(function(tx) {
database.executeSql(sqlCommand, [data.thingsToInsert], function (resultSet) {
console.log('success: insertIntoTable');
}, function (error) {
console.log('SELECT error: ' + error.message);
});
}, function(error) {
console.log('transaction error: ' + error.message);
database.close();
}, function() {
console.log('transaction ok: insertIntoTable');
});
};
app.js
ionic.Platform.ready(function () {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
};
if(window.StatusBar) {
StatusBar.styleDefault();
}
db = window.sqlitePlugin.openDatabase({name: 'myDbName.db', location: 'default'});
if (window.Connection) {
if (navigator.connection.type !== Connection.NONE) {
databaseFactory.createTables(db);
MyService.getStuffFromAPI().then(function(result) {
for (var index = 0; index < result[0].campaigns.length; index++) {
databaseFactory.insertIntoTable(db, result[0].campaigns[index]);
}
var selectResult = databaseFactory.selectFromCampaigns();
console.log(selectResult); //This log comes earlier than the above inserts could finish.
}, function(result) {
console.log(result);
});
}
}
});
The INSERT is working fine anyways, I did check it.
I know that the datebase.transaction is asynchronous so also tried it with single db.executeSQL command but had the same problem even with adding $q resolve, reject to the factory. I really could use some help, thanks!
Upvotes: 1
Views: 3306
Reputation: 199
The problem was the way I used the database.transaction(function (tx){})
since it's itself an asynchronous function and inside the function body I can make the synchronous CRUD operations and they will happen in order.
app.js (fixed)
ionic.Platform.ready(function () {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
cordova.plugins.Keyboard.disableScroll(true);
};
if(window.StatusBar) {
StatusBar.styleDefault();
}
db = window.sqlitePlugin.openDatabase({name: 'MagicalWonder.db', location: 'default'});
if (window.Connection) {
if (navigator.connection.type !== Connection.NONE) {
MyService.getMyPreciousData().then(function(result) {
db.transaction(function(tx) {
databaseFactory.createTable(tx);
for (var index = 0; index < result[0].campaigns.length; index++) {
databaseFactory.insertIntoTable(tx, result[0].myPreciousData[index]);
}
// HERE I CAN MAKE THE SELECT REQUESTS
}, function(error) {
console.log('transaction error: ' + error.message);
database.close();
}, function() {
console.log('transactions successfully done.');
});
}, function(result) {
console.log(result);
});
}
}
});
factory method (fixed)
factory.insertIntoTable = function (tx, data) {
var sqlCommand = 'INSERT INTO wanders (' +
'id, ' +
'magic_spell) values (?,?)';
tx.executeSql(sqlCommand, [data.id, data.magic_spell], function (tx, resultSet) {
console.log('Success: insertIntoBookOfWonder');
}, function (tx, error) {
console.log('SELECT error: ' + error.message);
});
};
Upvotes: 1
Reputation: 357
Every Insert returns a promise. Keep those promises in an array of promises and use $q.all to wait for all of them to complete.
Example: Factory method used to insert an object
function insert(object){
var deferred = $q.defer(); //IMPORTANT
var query = "INSERT INTO objectTable (attr1, attr2) VALUES (?,?)";
$cordovaSQLite.execute(db, query, [object.attr1, object.attr2]).then(function(res) { //db object is the result of the openDB method
console.log("INSERT ID -> " + res.insertId);
deferred.resolve(res); //"return" res in the success method
}, function (err) {
console.error(JSON.stringify(err));
deferred.reject(err); //"return" the error in the error method
});
return deferred.promise; //the function returns the promise to wait for
}
And then, in every insert:
promises.push(yourService.insert(obj).then(function(result){ //"result" --> deferred.resolve(res);
//success code
}, function(error){ //"error" --> deferred.reject(err);
//error code
}));
And finally:
$q.all(promises).then(function(){//do your selects}, function(err){//error!});
Hope it helps.
More info about $q and $q.all: https://docs.angularjs.org/api/ng/service/$q#all
And another example: https://www.jonathanfielding.com/combining-promises-angular/
Upvotes: 1