dexie / Dexie.js

A Minimalistic Wrapper for IndexedDB
https://dexie.org
Apache License 2.0
11.49k stars 642 forks source link

angular2 compatibility (1.4.0-beta.3) #251

Closed cherrydev closed 8 years ago

cherrydev commented 8 years ago

In 1.3.6 I was able to get dexie to play nicely inside of angular2 complete with async/await (through babeljs and typescript) by loading babel's polyfill.js, then zone.js and then finally dexie, but starting with 1.4.0-beta I get an error from zone.js Uncaught Error: More tasks executed then were scheduled. when attempting to do anything with Dexie. This problem persists with 1.4.0-beta2 and 1.4.0-beta.3. The problem happens regardless of preceding everything with: let Promise = Dexie.Promise btw.

I'm getting this error in test code with karma/jasmine, but am not actually using any angular2 infrastructure. zone.js is a requirement for ng2, though, so that's why I'm testing it with zone.js.

I'm concerned, generally, about Dexie's custom Promise implementation, but it did appear that I had it working correctly in 1.3.6 at least.

dfahlander commented 8 years ago

That concerns me too. Seems there are other people having same problem with various libs and zone.js pre 0.6.10. What's your version of zonejs?

cherrydev commented 8 years ago

0.6.12

dfahlander commented 8 years ago

If I inlclude zonejs, could I reproduce it easily in a unit test (qunit based)?

cherrydev commented 8 years ago

It seems likely you could. I have babel-polyfill@6.8.0 and zone.js@0.6.12 loaded via script tags and I'm using Dexie through typescript (1.8.7) configured to emit es6, and then piped through babel.

dfahlander commented 8 years ago

Do you just include dist/zone.js or do you activate it somehow?

cherrydev commented 8 years ago

zone.js and polyfill are being loaded through a script tag. Dexie is being loaded through external modules via browserify. Okay, so it appears that I currently can only reproduce this issue when I'm running it isolated in a karma/jasmine unit test. I do not see the same issue when running my actual ng2 application. I currently cannot even speculate as to why…

cherrydev commented 8 years ago

Note that I actually had some difficulty getting 1.3.6 working with Karma and Jasmine originally and I ended up needing to force Karma to load polyfill.js and zone.js before loading the jasmine framework or I got similar errors.

dfahlander commented 8 years ago

Do you anything new regarding this issue? Does Dexie v1.4.0 seem to break zone compatibility? I recall you had zone incompatibility in earlier versions of Dexie that you managed to work around by proxying Dexie.Promise.prototype.then. Could that workaround be an issue now when using Dexie v1.4.0?

One difference with in 1.4.0 is that Dexie will use true microticks in all cases where it's possible. This enabled me to simplify much of the code, since I could use Promise.then() without fearing a transaction loss. I'm probably also close to be able to support 3rd part promises soon (that uses true microticks).

How does Dexie behave in an Angular2 app? Does it need your zone.js workaround? Is the workarond Dexie-specific or does it just patch the IndexedDB API?

dfahlander commented 8 years ago

Updated the last comment (Wrote 1.3.6 but should be 1.4.0)

dfahlander commented 8 years ago

I'm about to release v1.4.0 soon but am a little frustrated over this issue. Anyone having tested Dexie 1.4.0-beta.3 with zone.js?

cherrydev commented 8 years ago

Sorry I haven't written back about this recently, I've been out of town. I stopped using my patch to Dexie.Promise.prototype.then when zone.js started natively patching the IndexedDB APIs, so there's none of my own code in between all of that. The extra frustrating part of this is that I can only see this behaviour when I'm running inside of a testing environment (in a karma runner with jasmine) and in an actual web environment I do not see this happening. Unfortunately automated tests are essential in my workflow so I can't use 1.4.

dfahlander commented 8 years ago

Seems we're not alone with this problem.

People get the same issues with Google maps API, jquery, etc.

Quote from https://github.com/angular/zone.js/issues/287:

"FYI disabled snippet is a workaround until issue is fixed in zone.ts line: 763 zone.ts"

if (next < 0) {
        debugger;
        throw new Error('More tasks executed then were scheduled.');
      }

Let's follow https://github.com/angular/zone.js/issues/287 to see if something will be fixed within zonejs.

dfahlander commented 8 years ago

I've created a repo with the whole stack setup except typescript-->babel. Very simple repo. But could not trigger the bug.

Would you have a chance looking at it? I'm including zone and babel-polyfill via karma.conf.js only so it's being included after jasmine and karma. Didn't find how to force the HTML to include stuff before all that.

https://github.com/dfahlander/dexie-issue-251

David

dfahlander commented 8 years ago

Another thing you could test (in your code), is the following that works in Dexie v.1.4:

Dexie.Promise.scheduler = function (fn, args) {
    Zone.current.scheduleMicrotask(()=>fn.apply(null, args));
};
cherrydev commented 8 years ago

I'll give it a try to help reproduce this.

cherrydev commented 8 years ago

Well, damnit. Now I can't reproduce the problem… I saw it on Wednesday and now it's gone. Sorry? Or I guess that's good? I thought the reason you weren't seeing it was because I was using angular's own versions of describe and it which wrap the tests in the setup calls needed for zone, but that didn't break yours and then for some reason it seemed to be working in mine. Odd.

cherrydev commented 8 years ago

Damnit, and it's back. head-desk!

cherrydev commented 8 years ago

https://www.npmjs.com/package/karma-source-map-support was the culprit! Now, I haven't the foggiest idea of why that karma plugin would cause this problem, but I'll leave it up to you as if you care to investigate it further or not.

dfahlander commented 8 years ago

Thanks much for looking into this problem and finding the root cause. I'll try reproduce it. I'll probably release dexie@1.4.0 on Friday unless something else would stop it. Again, thanks a lot!

dfahlander commented 8 years ago

It's happening in this line:

var NEEDS_THROW_FOR_STACK = !new Error("").stack;

When the Error.stack property getter is executed, it invokes the browser-source-map code that in it's turn makes a synchronous XMLHttpRequest.send(), which is intercepted by zone and not liked at all ;)

dfahlander commented 8 years ago

Closing this issue now. The issue needs to be fixed in Zonejs. It affects all libs that use the stack property of Error.prototype when having loaded karma-source-map-support and zonejs.

dfahlander commented 8 years ago

A recent commit to zonejs probably fixes this issue. I haven't verified though.