I've been working with Dexie JS to manage an IndexDB data store and now want to sync the data store with a remote database. The issue that I am having is that I want to nest all relational/child records under their respective parent records in a collection and then send the whole group/list off to the remote server, using some AJAX.
In practice, what I am seeing is that the child records are not present at the time they are pushed to the remote server. However, I do see them in console.log(). I know that this is because console.log() gets the actual data at a much later time than when the data is pushed remotely. I also know that this is a common issue with promise chains, but am somehow unable to solve it.
Here's what I have so far.
function PushRemote(items, modelName) {
console.log(items);
$.ajax({
type: 'POST',
url: '/' + modelName + '/AsyncSave',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify(DataTransferItemList),
success: function (response) {
iDB.open().then(function () {
return iDB.table(modelName).update(response, { isNotSynced: "false" });
});
},
error: function (response) {
console.error(response);
}
});
}
function PushTableToRemote(modelName) {
iDB.transaction('rw',
iDB.Comments,
iDB.CommentRatings,
iDB.Posts,
iDB.PostRatings,
iDB.Reviews,
() => {
iDB.table(modelName).where({ isNotSynced: "true" }).toArray(items => {
items.forEach(item => {
if (modelName == 'Comments') {
iDB.CommentRatings.where({ CommentId: item.CommentId }).toArray(c => item.CommentRatings = c);
}
if (modelName == 'Posts') {
iDB.PostRatings.where({ PostId: item.PostId }).toArray(p => item.PostRatings = p);
}
})
return items;
})
.then(items => {
if (items && items.length > 0) {
PushRemote(item, modelName);
}
});
});
}
pushTableToRemote('Comments');
Alright, so it turns out if you can't go through the promise chain, then you go around the promise chain. ;)
Ended up implementing spawn()
and yield
with a generator function, instead of a promise chain (https://dexie.org/docs/Simplify-with-yield.html). This was way more straight forward, for me at least. And worked like a charm. Your mileage may vary.
function PushTableToRemote(modelName) {
spawn(function* () {
var items = yield iDB.table(modelName).where({ isNotSynced: "true" }).toArray();
if (items && items.length > 0) {
if (modelName == 'Comments') {
for (var i = 0; i < items.length; i++) {
var CommentRatings = yield iDB.CommentRatings.where({ CommentId: items[i].CommentId }).toArray();
items[i].CommentRatings = CommentRatings;
}
}
if (modelName == 'Posts') {
for (var i = 0; i < items.length; i++) {
var PostRatings = yield iDB.PostRatings.where({ PostId: items[i].PostId }).toArray();
items[i].PostRatings = PostRatings;
}
}
PushRemote(items, modelName);
}
});
}