How to wait for a bluebird promise to settle in multiple locations?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


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);
});





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


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.

Popular posts from this blog

Makefile test if variable is not empty

Will Oldham

'Series' object is not callable Error / Statsmodels illegal variable name