Zotero.DB.query = Zotero.Promise.coroutine(function*() {
return (yield Zotero.DB.queryAsync.apply(Zotero.DB, arguments));
});
to mimic the code flow I could use under 4.0? What are the downsides/pitfalls to such?
Thanks,
Emile
--
You received this message because you are subscribed to the Google Groups "zotero-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to zotero-dev+...@googlegroups.com.
To post to this group, send email to zoter...@googlegroups.com.
Visit this group at http://groups.google.com/group/zotero-dev.
For more options, visit https://groups.google.com/d/optout.
Hi,
I've looked at those, but I can't yet resolve them with how I see the queryAsync calls being used in Zotero master. The way I've seen promises used is in 'then' chains, but I see "yield Zotero.DB.queryAsync" calls in the middle of functions in the Zotero code; if those return immediately and the code after it proceeds immediately, how does that work? Or should the coroutine enclose all yield code to have that chunk within the coroutine mimic sync behavior? I've read the link you point to, but I couldn't make it out from that.
You received this message because you are subscribed to a topic in the Google Groups "zotero-dev" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/zotero-dev/30l_4rNyXC0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to zotero-dev+...@googlegroups.com.
That is really how I had interpreted it, but then I don't understand why my code above wouldn't work. It's a generator, it yields, so why wouldn't it just stop the caller too?
Since javascript is single threaded, stopping anywhere in a synchronous call to wait for something asynchronous to execute would not work, since the whole javascript engine would have to halt and of course there would be nothing to execute the asynchronous tasks. So a generator does not halt anything. It just returns a value and remembers where it stopped.
Let's try an example
```
var getValue = Zotero.Promise.coroutine(function*() {
alert("generator started")
var val = yield Zotero.DB.valueQueryAsync("SELECT 5");
alert(val);
return val*5;
});
var foo = getValue();
alert("foo is " + typeof foo);
foo.then(function(v) { alert(v); });
alert("end");
```
Ok, so the alerts you should get are in the following order:
"foo is object" (since it's a promise)
"end"
"generator started"
"5"
"25"
Following along the flow of the program:
* we create the getValue function, nothing interesting happens
* we call getValue. BlueBird immediately returns a promise that will be fulfilled with the return value of the generator
* we alert that foo is object
* we set up what happens once foo is fulfilled
* we alert "end"
* [some time passes, javascript engine does whatever it wants]
* BlueBird starts processing the generator. It calls it once.
* we alert that generator has started
* generator yields a promise back to BlueBird and it's done (it doesn't wait for BlueBird to return anything. It's stack is cleared). The promise will be fulfilled once SQLite engine returns a value. BlueBird goes to sleep (not explicitly)
* [some time passes and SQLite calls back BlueBird via promise]
* BlueBird calls the generator again, passing back the value from SQLite.
* generator resumes from where it yielded last with the value it was passed back.
* we alert "5"
* generator returns a value
* BlueBird notices that generator is done and it returned a value, so it fulfills foo.
* [some time passes]
* function declared in foo.then is called with foo fulfillment value
* we alert "25"
Hopefully this helps (and hopefully this doesn't come out very mangled)
You received this message because you are subscribed to the Google Groups "zotero-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to zotero-dev+...@googlegroups.com.
Since javascript is single threaded, stopping anywhere in a synchronous call to wait for something asynchronous to execute would not work, since the whole javascript engine would have to halt and of course there would be nothing to execute the asynchronous tasks. So a generator does not halt anything. It just returns a value and remembers where it stopped.
Let's try an example
On 7/5/15 10:09 AM, Emiliano Heyns wrote:
> Is it possible to do async DB queries on 4.0.27+ in some way? It'd
> ease my development process if there'd be a way to prepare as much as
> possible for 5.0 on the 4.0 branch.
Async DB queries are 5.0 only, but you don't particularly need Zotero
calls to actually be async in order to make your own code async now. Any
function of yours that does a DB query should just be a coroutine, so
that when you switch from query() to queryAsync() or from
beginTransaction()/commitTransaction() to executeTransaction() you just
add yields.
<lots of clarifying examples>
The upshot of all this is that async code is pretty viral, which is why
we had to rewrite essentially the entire code base. See my explanation
in #518 [2], though, of one way we've tried to reduce inline promises
and the spread of asnyc code — by preloading data and having getters
simply throw an error if data isn't yet loaded.
[1]
https://github.com/petkaantonov/bluebird/blob/master/API.md#promisemethodfunction-fn---function
[2] https://github.com/zotero/zotero/issues/518
var item = yield Zotero.Items.get(123);
var title = yield item.getField('title');
var date = yield item.getField('date');
andvar item = yield Zotero.Items.get(123);
try {
var title = item.getField('title'); // item data not yet loaded; throws an error
}
catch (e) {}
yield item.loadItemData(); // this is a no-op if data is already loaded
var title = item.getField('title');
var date = item.getField('date');
In practice, both snippets will have to be part of an async function; so you lose one yield, but you gain at least one extra line of code to do so (excluding for now the try-catch block -- I don't know whether its intent is to demonstrate getField throwing an error, or that the try-catch has a desirable side-effect that I'm missing).I see. But what is the pragmatic difference between
andvar item = yield Zotero.Items.get(123); var title = yield item.getField('title'); var date = yield item.getField('date');
In practice, both snippets will have to be part of an async function; so you lose one yield, but you gain at least one extra line of code to do sovar item = yield Zotero.Items.get(123); try { var title = item.getField('title'); // item data not yet loaded; throws an error } catch (e) {} yield item.loadItemData(); // this is a no-op if data is already loaded var title = item.getField('title'); var date = item.getField('date');
(excluding for now the try-catch block -- I don't know whether its intent is to demonstrate getField throwing an error, or that the try-catch has a desirable side-effect that I'm missing).
How much time do I have for the 5.0 transition? I don't really have the time to maintain two separate versions, so ideally I'd want to release a 5.0-compatible BBT within hours of Zotero releasing 5.0.