-
Notifications
You must be signed in to change notification settings - Fork 297
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Drop jQuery dependency in documentation/examples #123
Comments
Thanks! Planned it. Feel free to do a PR, otherwise I will do it some time after March 27 |
I'm so confused about Promises, I'm trying to follow the examples in my stimulus controller, and I get depressed and start questioning my career choices... Since a jquery ajax request returns a jQuery promise, (see What I'd really like to see is a set of paginated api calls, so I could properly load an set of data, e.g.
Anyway, this is an awesome library, I can't wait to understand Promises more so I can take advantage of it. |
Here's an example that works with dummy data. It only gets the first 30 out of 100 though, it'd be great if you could tweak it to show fully populating the table via a sequence of API calls. import Dexie from 'dexie';
var db = new Dexie('someDB');
db.version(1).stores({
productTable: "++id,price,brand,category"
});
// Populate from AJAX:
db.on('ready', function (db) {
// on('ready') event will fire when database is open but
// before any other queued operations start executing.
// By returning a Promise from this event,
// the framework will wait until promise completes before
// resuming any queued database operations.
// Let's start by using the count() method to detect if
// database has already been populated.
return db.productTable.count(function (count) {
if (count > 0) {
console.log("Already populated");
} else {
console.log("Database is empty. Populating from ajax call...");
// We want framework to continue waiting, so we encapsulate
// the ajax call in a Promise that we return here.
return new Promise( (resolve, reject) => {
const response = loadData().then( (response) => {
console.log("Calling bulkAdd() to insert objects...", response);
console.assert(db);
return db.productTable.bulkAdd(response.products);
});
}).then(function (data) {
console.log("Got ajax response. We'll now add the objects.");
// By returning the a promise, framework will keep
// waiting for this promise to complete before resuming other
// db-operations.
}).then(function () {
console.log ("Done populating.");
});
}
});
});
// Following operation will be queued until we're finished populating data:
db.productTable.each(function (obj) {
// When we come here, data is fully populated and we can log all objects.
console.log("Found object: " + JSON.stringify(obj));
}).then(function () {
console.log("Finished.");
}).catch(function (error) {
// In our each() callback above fails, OR db.open() fails due to any reason,
// including our ajax call failed, this operation will fail and we will get
// the error here!
console.error(error.stack || error);
// Note that we could also have caught it on db.open() but in this sample,
// we show it here.
});
async function loadData() {
let url = 'https://dummyjson.com/products';
const response = await fetch(url);
return await response.json();
} |
Some of the old examles would really need a rewrite and this is one of them. In this case I don't think we need to create a Promise there but simply: db.on('ready', async vipDB => {
const count = await vipDB.productTable.count();
if (count > 0) {
console.log("Already populated");
} else {
const data = await loadData();
await vipDB.productTable.bulkAdd(data);
console.log ("Done populating.");
}); The db instance passed to on('ready') is "VIP" meaning that it lets the request bypass the blocked queue that waits for the promise from the callback to complete before resuming other request. If you want to fetch several chunks of data rather than a single one it could be done entirely within loadData(). I would also like to change If you would have the time to do a PR and update this example, please verify that the code runs and does what it is expected to do (I haven't actually run the snippet I posted). Else, I will update these docs some day - it's too much other things I need to prioritize right now. Thanks for taking bringing this up. The docs feel a bit old fashioned with these old samples. |
I'll play around with this -- I'm working on a demo where I preload data for use with the awesome datatables.net, and now that pagination is working, it looks great. I'll submit a PR hopefully later today. How can I optionally delete the database first, before populating? I'll add that to this example. This isn't working, I'm sure I need to wait for the delete to finish before doing the next step. In fact, I seem to have gone into a Promises wormhole, and 'ready' seems to never fire now. Sigh. By chance, is there a way to turn on debug and see the events that are fired? My code is filled with console.logs, I'm sure I'm doing something wrong with promises.
var db = new Dexie('test');
if (forceReload) {
db.delete().then( () => db = new Dexie('test'));
}
// Populate from AJAX:
db.on('ready', (db) => {
// db.delete().then( () => {});
db.version(1).stores({
productTable: "++id,price,rating,brand",
friendTable: "++id,state,age,zip"
}); |
I'm sure this is something easy, but I can't wrap my head around the promises. Here's a jsFiddle with the example you provided. https://jsfiddle.net/tacman1123/1uhvg5nw/1/ I can see that is it loading the data, but the count promise is never filled, almost certainly because something is out of order. Thanks |
There are 2 problems with the loadData() in the fiddle.
I do not know about the dummyjson API but I suppose you can call it several times to download chunks of the data. This is outside the scope of Dexie but typically you could do a for...of loop and await each result. You could either build up an entire result to return from loadData(), or maybe better, let loadData do bulkAdd after each chunk has been downloaded. |
Thanks! The updated and working fiddle is at https://jsfiddle.net/tacman1123/1uhvg5nw/2/ Should I make a PR using this code to replace the jQuery example? |
Yes but just remove |
On https://dexie.org/docs/Dexie/Dexie.on.populate#ajax-populate-sample
fetch() is supported on all browsers that support IndexedDB, using jquery in the documentation makes this library seem a bit "old-school", back when jquery was used to harmonize all the different ways ajax calls were made.
I think developers may simply cut and paste when getting started, so using something that works everywhere and was also a best practice for handling errors would be better than requiring jQuery.
Thanks.
The text was updated successfully, but these errors were encountered: