How to wait for a bluebird promise to settle in multiple locations?
How to wait for a bluebird promise to settle in multiple locations?
I have a situation where a bunch of functions are needing to wait for a promise to settle because it's the init function;
self.init=new Promise(function(resolve){
//do stuff, take awhile
resolve();
});
But, while it's init'ing, the async nature means other functions that depend on it being init are being called. I want those functions to wait for the init to finish, then continue.
I tried doing this inside each function
function doSomethingUseful(){
self.init.reflect().then(function () {
//do functions purpose
});
}
function doSomethingUseless(){
self.init.reflect().then(function () {
//do functions purpose
});
}
But it only works randomly, probably only works if init has settled, and if it hasn't, it just hangs here, weirdly hangs the whole app, despite it being async.
I am trying to replace a former solution that involved intervals and checking a Boolean isInit in each function call.
Is there a bluebird function to do this? Or another way to keep waiting and checking on a promise to see if it is resolved?
The app has this sort of structure in a number of places. Usually around sqlite read/writes. An init to open the database, but while it's opening, the page is loading and it's already trying to read/write to the tables, so those read/writes are forced to wait by using setInterval and repeatedly checking to see if the init has finished.
Here's an example using google analytics.
function Analytics() {
var self = this;
self.ready = ko.observable(false).subscribeTo('application:ready'); //attached to page ready event in jquerymobile and cordova
self.trackerInit = new Promise(function (resolve, reject) {
ko.computed(function () {
if (self.ready()) {
window.ga.startTrackerWithId('id', 1000, resolve, reject);
}
});
});
}
Analytics.prototype.trackSpeed = function (cat, interval, variable, label) {
var self = this;
console.log("speed tracker", cat, interval, variable, label); //this logs
return self.trackerInit.then(function () {
console.log("speed tracker confirm init"); //this never logs, all execution stops including other async code
return new Promise(function (resolve, reject) {
window.ga.trackTiming(cat, interval, variable, label, resolve, reject);
});
}).catch(function (e) {
if (e.message === "send timeout") {
return true; //who cares about timeouts anyways
} else {
throw e;//rethrow it
}
});
};
Function is called within page change event without a return, purely async. Calling it causes all execution to stop.
The ready ko is done like this
self.ready = ko.observable(false).publishOn('application:ready');
var deviceReady = new Promise(function (resolve) {
$(document).on('deviceready', resolve);
});
var pageReady = new Promise(function (resolve) {
$(document).on('pagecreate', resolve);
});
Promise.all([deviceReady, pageReady]).then(function () {
//a couple of page of code and...
self.ready(true);
});
Changing the init like this produces the same result of a hang when checking it's results
self.trackerInit = new Promise(function (resolve, reject) {
console.log("initting");
checker = setInterval(function () {
if (window.ga) {
console.log("ready init");
window.ga.startTrackerWithId('UA-23249898-11', 100, function(){
clearInterval(checker);
console.log("init complete");
resolve();
}, reject);
}
}, 1000);
});
isInit
Can you post the code for ko observable
subscribeTo
method?– Brandon
21 mins ago
subscribeTo
@Brandon Added page ready
– Trevor D
18 mins ago
it's the subscribeTo and publishOn that interests me
– Brandon
13 mins ago
That's this tool. github.com/rniemeyer/knockout-postbox I also had this problem using a simpler setInterval combined with checking for window.ga to be set. I just need a way to watch for window.ga to be set before I can run startTrackerWithId.
– Trevor D
12 mins ago
1 Answer
1
They are just promises. Just use then
to chain them
then
function doSomethingUseful() {
// wait for init to finish, then do our stuff
// return the new chained promise in case someone wants to wait on us
return self.init.then(function () {
// do stuff
});
}
function doSomethingUseless() {
// wait for init to finish, then do our stuff
// return the new chained promise in case someone wants to wait on us
return self.init.then(function () {
// do stuff
});
}
// do both of those things and then do something else!
Promise.all([doSomethingUseful(), doSomethingUseless()]).then(function () {
console.log("init is done. And we've done something useful and useless.")
}
doesn't this run
init
multiple times, which is probably not desired?– William Chong
37 mins ago
init
in the OP,
init
is not a function. It is a Promise. So no it will only run once (a promise only ever runs once)– Brandon
36 mins ago
init
That causes it to hang again. Usually only on slower devices that haven't finished the init before the check
– Trevor D
35 mins ago
you need to post a more complete example. You don't show where you setup
init
or where you call your other functions. Without seeing how you string them altogether we can't help find the problem– Brandon
34 mins ago
init
@Brandon edited with more examples
– Trevor D
25 mins ago
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
how about a boolean
isInit
for the init loaded case, and a promise queue that gets resolved immediately after init is done for the init still-loading case?– William Chong
42 mins ago