Q.js and order of execution confusion within ASP.NET MVC - javascript

I have adopted the library Q.js into my program to try and solve some problems with the order of execution in my code, I am new to promises and deferred in general, so this is a pretty difficult step for me.
At this point in time, I am using Q v1 within ASP.NET MVC, and therefore I am using Visual Studio 2013.
Now, the actual code for what I am doing is a great deal longer than this, but I'll attempt to be concise, as I often get told my questions are too long and verbose.
I start by including q.js and require.js normally, nothing special is going on here. It works fine, it compiles, it runs, all is happy and well.
#Scripts.Render("~/scripts/q")
#Scripts.Render("~/scripts/require")
<script type="text/javascript">
Q().then(function(){
// some code executes here.
$.blockUI(); // the whole page is blocked while loading.
console.log("[1] first step. blocking the page.");
}).then(function() {
console.log("[2.1] starting the second step.");
require(['home/app/init'], function(app) {
console.log("[2.2] within the require function.");
new app.init().wiring(); // this does some preliminary stuff for the app
});
console.log("[2.3] outside of the require function.");
}).then(function() {
console.log("[3.1] made it to the third step. stuff happens.");
});
</script>
Now, running this code, the console output for 2.1 and 2.3 are visible before 2.2 - which is the crux of the problem. I want it to run in order. So I dug a bit more, and found this suggestion; changing my require call to look more like this was suggested to me ..
// ....
.then(function(){
var promise = Q.when(require['home/app/init'], function(app) {
console.log("[2.2.1] within the require");
new app.init().wiring();
}).then(function() {
console.log("[2.2.2] I expect to see this after 2.2.1");
});
console.log("[2.3] outside of the require function.");
});
Now I get that 2.3 will still run before 2.2.1, but I'm still seeing 2.2.2 running before 2.2.1 - and I thought that wrapping the behavior in the Q.when(fn) was supposed to fix that?
Can someone help me understand why these are not running in the order I am asking them to?
For a bit more information, the file home/app/init is actually a Typescript file that looks a bit like this;
home/app/init.ts
export class init {
public function wiring() {
// some simple things happening here, nothing special.
}
}
I am not sure if this question qualifies to have the ASP.NET MVC tag, but the fact that I am using that framework is paramount to the tooling I use, which does have influence over what I can do (for instance, I'm having a hard time with things involving node.js because of Visual Studio) - so I am tagging it explicitly to be sure people realize the kind of development environment I am in.
Update
I have made a bit of progress on this, though I am still a bit uncertain. At the moment, the following code seems to run more in the order I am expecting.
// .....
.then(function(){
console.log("[2.1]");
// create a deferred promise
var deferred = Q.defer();
require(['home/app/init'], function(app) {
// we are inside the require function
console.log("[2.2]");
// run the actual method
new app.init().wiring();
// report back to the console.
console.log("[2.3]");
// resolve the promise
deferred.resolve();
});
console.log("[2.4]");
Q.when(deferred.promise).then(function() {
console.log("[2.5]");
}).then(function(){
// ... continue
});
This at least seems to cause the code to pause and wait for the require to finish before it goes on to 2.5, but I'm not sure if this is the correct way to do this with Q.js.

2.1 will run before 2.2 because that's the order you are running the code but the 2.2 code runs asynchronously so gets run once require has got everything in order which will take more time than it takes the 2.3 code to execute
I think in your second block of code you want to move the 2.2.2 block inside the when see the documentation for when at the bottom of this page
https://github.com/kriskowal/q

Related

How do I detect when Emscripten's generated .js finishes loading the wasm so I can run my JS functions which call it?

I'm using Emscripten to compile some C code to WebAssembly. This is the final emcc call in my Makefile:
emcc $(CFLAGS) iva.a -o iva.js
Which works as intended and generates a .js file and a .wasm file. The JS is loaded into my HTML page as follows:
<script src="../dist/iva.js">
And it loads and instantiates the WebAssembly code iva.wasm properly. This message appears in the console soon after I load the page:
Fetch finished loading: GET "http://localhost:6931/dist/iva.wasm".
Which I take to mean that my WebAssembly is loaded through a fetch() and, perhaps pending some processing, I can access my functions through the console:
Module._init_display_system()
And get the return values. This holds true and everything works.
Clearly, I should be able to do this through a script as well. However, I can't see a way to only run a function after my WebAssembly has been instantiated. I get the feeling that I'm missing something rather obvious.
Anyway, how do I do this?
Use Module['onRuntimeInitialized'].
Module['onRuntimeInitialized'] = function() {
console.log("wasm loaded ");
var x=Module.ccall("doubleIt","number",["number"],[20]);
alert(x);
}
You have used emsdk, there are online WASM compilers like Wasmfiddle. Find my github repo useful for both the methods.
While the two solutions of Sudhakar RS and Anil8753 are totally fine, I want to add, that you have to execute this approach before you load your WebAssembly. Otherwise it might be too late to catch the event.
Besides that, there is another approach, which uses promises. If you add
-s MODULARIZE=1 -s 'EXPORT_NAME="createMyModule"'
as options when compiling with emcc, your resulting .js will contain the function createMyModule. This function will return a Promise that resolves as soon as your WebAssembly code is ready to use. Example usage:
In your HTML, add your WebAssembly as you already did:
<script src="../dist/iva.js">
In your js, call the function and after the promise resolved, you are good to go:
createMyModule().then(MyModule => {
console.log('WebAssembly loaded!');
// Access your functions (if bound by Embind):
console.log(MyModule.getSomething());
});
<script>
var Module = {
onRuntimeInitialized: function() {
console.log('module loaded');
}
};
</script>

How can I detect when an AngularJS app is finished loading a page using JavaScript?

I'm trying to write Robot Framework tests to cover certain use cases for a third party AngularJS app.
I have the requirement that I need to use Python 3.5+ and SeleniumLibrary (rather than the old Selenium2Library).
I've attempted to adapt the wait_until_angular_ready keyword from https://github.com/rickypc/robotframework-extendedselenium2library to work outside of the context of this library, updating it to work with Python 3.5+ and SeleniumLibrary.
The keyword executes the following JavaScript to check when Angular is Ready, but it seems to always return true immediately
var cb = arguments[arguments.length-1];
if(window.angular){
var $inj;
try {
$inj = angular.element(document.querySelector('[data-ng-app],[ng-app],.ng-scope')
||document).injector()
||angular.injector(['ng'])
} catch(ex) {
$inj = angular.injector(['ng'])
};
$inj.get = $inj.get||$inj;
$inj.get('$browser').notifyWhenNoOutstandingRequests(function() {
cb(true) // it's always returning here
})
} else {
cb(true)
}
This is called from within my version of the wait_until_angular_ready keyword which is located in a class which subclasses the SeleniumLibrary WaitingKeywords class.
The code which executes the Js looks like
WebDriverWait(self.driver, 100, 0.1). \
until(lambda driver: driver.execute_async_script(script), error)
Have I made a mistake here or is this not the correct way to check when angular has finished rendering the page? I will admit that I am not very familiar with AngularJS
Probably you resolved this issue, but if anyone in the future have the same inconvenience can use this library for Angular in Robot framework: https://github.com/Selenium2Library/robotframework-angularjs
you can use document.readyState , it will return "complete" as a response if the page is rendered completly.

Running client side javascript without loading a new (blank) view on Odoo 8

I need to run some client-side javascript from a button in a form view in Odoo 8. This button runs a python method which returns this dictionary:
{"type": "ir.actions.client",
"tag": "my_module.do_something",}
do_something is defined in a .js file as follows:
openerp.my_module = function (instance) {
instance.web.client_actions.add("my_module.do_something", "instance.my_module.Action");
instance.my_module.Action = instance.web.Widget.extend({
init: function() {
// Do a lot of nice things here
}
});
};
Now, the javascript is loaded and executed properly, but even before launching the init function, Odoo loads a brand new, blank view, and once the javascript is over I can't get browse any other menu entry. In fact, wherever I click I get this error:
Uncaught TypeError: Cannot read property 'callbackList' of undefined
What I need instead is to run the javascript from the form view where the button belongs, without loading a new view, so both getting the javascript stuff done and leaving all callbacks and the whole environment in a good state. My gut feeling is that I shouldn't override the init funcion (or maybe the whole thing is broken, I'm quite new to Odoo client-side js) , but I couldn't find docs neither a good example to call js the way I want. Any idea to get that?
Sorry, I don't work on v8 since a lot of time and I don't remember how to add that, but this might help you: https://github.com/odoo/odoo/blob/8.0/doc/howtos/web.rst
Plus, if you search into v8 code base you can find some occurence of client actions in web module docs https://github.com/odoo/odoo/search?utf8=%E2%9C%93&q=instance.web.client_actions.add
Thanks to the pointers simahawk posted in another answer, I have been able to fix my js, which is now doing exactly what I needed. For your reference, the code is as follows:
openerp.my_module = function (instance) {
instance.web.client_actions.add("my_module.do_something", "instance.my_module.action");
instance.my_module.action = function (parent, action) {
// Do a lot of nice things here
}
};

RequireJS define Browser Race Condition

We have a client-side plug-in framework that is constructed of modules (AMD) and utilizes require.js. In this framework we expose a public object that consists of configuration properties and common framework functionality. All of the required functionality for the public object is contained in one file (albeit separated into modules); the only file required by the end-user to add to their page.
The issue we are seeing is most prevalent in Safari but also shows itself occasionally in IE and Chrome. 100% of the time in Safari with an empty cache we encounter a race condition. Consider this example client code which is in the body of the client’s page.
<script type=”text/javascript”>
Me.subscribe(‘someEvent’, someHandler);
</script>
‘Me’ is always available to the page as its global and outside of any define call. However, ‘Me.subscribe’ is wrapped in ‘define’ and results in ‘undefined’ with the conditions I stated above.
We can’t tell the client to use any third-party frameworks to work around this issue. The code block above must stay exactly as it is.
I’ve been playing with the idea of allowing certain public function binding to be deferred without any additional work required by the client. So far, this is what I’m considering adding to the framework:
Me.deferred = function (fn, name) {
if (fn) return fn;
fn = this;
return function () {
var args = Array.prototype.slice.call(arguments);
setTimeout(function () {
fn[name].apply(this, args);
}, 0);
};
};
Then, in the framework near the top, I can add items I want deferred like this:
Me.subscribe = Me.deferred(Me.subscribe,'subscribe');
My questions are these: Am I missing something that is already out there? Is there an existing pattern that I am not aware of to handle this exact case? Is this just a bad idea in general?
If possible, make sure the client puts requireJS and all dependencies in the head. 'Me' can include an on-demand call which executes on creation if that is not possible.

sequential functions javascript

I'm having major trouble getting my app to behave while loading. I don't think it is very fair to users to allow them access to the app until it's finished loading and is ready / responsive.
Please note: every thing else works fine in my app I just can't get functions to run in order.
function LOADINGapp(){
//app loads but allows user to enter before loading is finished
$.when(getToday()).then(reorderdivs()).then(getSomething()).then(setupSomethingElse()).then(loadAnotherSomething()).then(INITapp());
//app stops dead at getToday but (Crome javascript console) no errors
getToday(function(){reorderdivs(function(){getSomething(function(){setupSomethingElse(function(){loadAnotherSomething(function(){INITapp();});});});});});
//app loads but allows user to enter before loading is finished
getToday(reorderdivs(),getSomething(),setupSomethingElse(),loadAnotherSomething(),INITapp());
//getToday();
//reorderdivs();
//getSomething();
//setupSomethingElse();
//loadAnotherSomething();
//INITapp();
}
function INITapp(){
$('#SPLASH').hide();
}
Can someone please assist me, I don't understand. Done and doing a tone of research to get this to behave.
Thanks
I haven't used when/then from jquery before, but it looks like you need to pass the pointers to the methods. Right now you are actually executing them all at once. Try:
$.when(getToday())
.then(reorderdivs)
.then(getSomething)
.then(setupSomethingElse)
.then(loadAnotherSomething)
.then(INITapp);
(Notice the missing parentheses)
Also, be aware the only true asynchronous object in JS is an AJAX call. setTimeout is NOT asynchronous, it is a queueing method. Read John Resig's post:
http://ejohn.org/blog/how-javascript-timers-work/
I solved it by jumping (only allowing my LOADINGapp function to do one thing at a time) so it works in stages. once a stage (a function) is complete it jumps back into the LOADINGapp function.
var L=0;
function LOADINGapp(){
if(L==0){getToday();}
else if(L==1){reorderdivs();}
else if(L==2){getSomething();}
else if(L==3){setupSomethingElse();}
else if(L==4){loadAnotherSomething();}
else if(L==5){INITapp();};
}
function INITapp(){
$('#SPLASH').hide();
}
example:
function getSomething(){
//app suff
//app suff
//app suff
L = 3;
LOADINGapp();
}
the only thing I will improve is just do L++; at the end of LOADINGapp as it saves writing it all over the place. PS:thanks for the efforts guys
It is probably something to do with asynchronous functions. So you could try making those functions with a callback, as mentioned here: http://pietschsoft.com/post/2008/02/JavaScript-Function-Tips-and-Tricks.aspx.

Categories

Resources