I need a simple way to avoid callback nests in javascript - javascript

I have a NPAPI plugin that I changed to native messaging, NPAPI is synchronous and so was the plugin. since chrome ditched NPAPI for good
Now that I have to change it to asynchronous calls, I am trying to find a way to handle the callbacks . I have wrapped the messaging into a class to handle a specific message from content script to background script.
I am handling the callbacks inside the class through setting it to internal array of callbacks functions as well as function specific result callbacks
However I am find difficulty in changing page code
as an example
lets assume the old code was like
res = npClass.function1 (var1,var2);
if(res == 'someval')
npClass.function2()
npClass.function1(var2,res.substring(2,3))
and so on
now that all functions are async I have to change the code to be more or less like this
npClass.function1(var1,var2, function(res)
{
if(res == 'someval')
npClass.function2(function(){
npClass.function1(var2,res.substring(2,3), function(res)
{});
npClass.function1(var2,res.substring(2,3);
}
}
and the nesting will go on and on this isn't how I expect it to be.
All I can think of is right now is that may be if I change the page code to make the parts of code that uses the extension as a class that inherits from the other message handling class then I can use the internal structure to invoke callbacks on the new class callbacks in messaging class
But even if I do this my code will be very fragmented
it will be something like this
PageClass.prototype.functionL()
{
functions1(functionb) 'from inheritance
}
PageClass.functionb(res)
{
if(res == 'some value)
function2( functionq) 'from inheritance
}
Still this is not suitable for me and I am sure I will have to handle a lot of stuff in it plus this will require a huge change in the structure of the page code.
I have searched all around to find any way to make async call sync in javascript but didn't find any plausible solution.
I am not expert in javascript and I need ideas to explore,
can someone here guide me

Related

Functionally test that an Element is visible (no elements covering) with Intern

I am currently using the JavaScript framework Intern to test my site, I am wanting to ensure that specific element's are truly visible. Intern currently has an option "isDisplayed" which half does this. But what I am wanting to also do is check that it would be truly visible to the user and that any other elements on the page do not cover (perhaps by z-index issues) etc.
Does anyone have an suggestions?
Thanks in advance.
Usually, it's better to focus on your unit tests and make sure the styles you expect to be setting are coming back correctly from the utility/helper functions you use to do so. Otherwise, you're going to end up testing things you probably don't mean to, such as functionality of the browser itself to compute the styles. Therefor, it's bad practice in many situations.
However, if you do need this, such as when testing a 3rd party JavaScript library against a customer's site, Intern's Leadfoot provides a .execute() method you'll want to use.
Example:
return this.remote // represents the browser
.get('mysite.com') // navigate to a page
.execute( // send a callback to the browser
function (selector) {
var elem = document.querySelector(selector),
result;
// collect some data for analysis...
result = getComputedStyle(elem).zIndex;
return result;
},
['div'] // arguments to send to the remote callback
)
.then(
function (zIndex) {
// analyze the data and make assertions about it...
assert(zIndex > 999);
}
);
Please note: This is awesome but be careful. Most of your test runs inside of Node.js, but the callback to .execute() does not and so it does not have access to any of your previously defined variables, etc.
As for strategies to determine when an element is truly visible to the user, it's very subjective, but getBoundingClientRect() is going to be your friend for determining when one element is overlapping another. There are good techniques here: Determine visibility / real z-index of html elements

Dynamically Included Javascript and Dependencies

So, as a sort of exercise for myself, I'm writing a little async script loader utility (think require.js, head.js, yepnope.js), and have run across a little bit of a conundrum. First, the basic syntax is like this:
using("Models/SomeModel", function() {
//callback when all dependencies loaded
});
Now, I want to know, when this call is made, what file I'm in. I could do it with an ajax call, so that I can mark a flag after the content loads, but before I eval it to mark that all using calls are going to be for a specific file, then unset the flag immediately after the eval (I know eval is evil, but in this case it's javascript in the first place, not json, so it's not AS evil). I'm pretty sure this would get what I need, however I would prefer to do this with a script tag for a few reasons:
It's semantically more correct
Easier to find scripts for debugging (unique file names are much easier to look through than anonymous script blocks and debugger statements)
Cross-domain requests. I know I could try to use XDomainRequest, but most servers aren't going to be set up for that, and I want the ability to reference external scripts on CDN's.
I tried something that almost got me what I needed. I keep a list of every time using is called. When one of the scripts loads, I take any of those using references and incorporate them into the correct object for the file that just loaded, and clear the global list. This actually seems to work alright in Firefox and Chrome, but fails in IE because the load events seem to go off at weird times (a jQuery reference swallowed a reference to another type and ended up showing it as a dependency). I thought I could latch on to the "interactive" readystate, but it doesn't appear to ever happen.
So now I come asking if anybody here has any thoughts on this. If y'all want, I can post the code, but it's still very messy and probably hard to read.
Edit: Additional usages
//aliasing and multiple dependencies
using.alias("ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js", "jQuery");
using(["jQuery", "Models/SomeModel"], function() {
//should run after both jQuery and SomeModel have been loaded and run
});
//css and conditionals (using some non-existant variables here)
using.css({ src: "IEFix", conditionally: browser === "MSIE" && version < 9 });
//should include the IEFix.css file if the browser is IE8 or below
and to expound more on my response below, consider this to be file A (and consider the jquery alias from before to be there still):
using(["jQuery", "B"], function() {
console.log("This should be last (after both jQuery and B have loaded)");
console.log(typeof($));
});
Then this would be B:
using("C", function() {
console.log("This should be second");
});
And finally, C:
console.log("This should be first");
The output should be:
This should be first
This should be second
This should be last (after both jQuery and B have loaded)
[Object Object]
Commendable that you are taking on such an educational project.
However, you won't be able to pull it off quite the way you want to do it.
The good news is:
No need to know what file you are in
No need to mess with eval.
You actually have everything you need right there: A function reference. A callback, if you will.
A rough P-code for your using function would be:
function using(modules, callback) {
var loadedModules = []
// This will be an ajax call to load things, several different ways to do it..
loadedModules[0] = loadModule(modules[0]);
loadedModules[1] = loadModule(modules[1]);
// Great, now we have all the modules
// null = value for `this`
callback.apply(null, loadedModules);
}

Markdown syntax highlighting in Javascript

I am trying to get the rainbow syntax highlighting library to work with the marked markdown rendering engine. The marked documentation states that a syntax highlighter is supported through the following configuration option:
marked.setOptions({
highlight: function(code, lang) {
return highlighter.javascript(code);
}
});
The rainbow source code indicates that passing in a string to highlight is supported via the following syntax:
Rainbow.color(code, lang, success);
I'm a bit at a loss as to how to put the two together. Specifically, success is a callback that will be called asynchronously, and I can't simply return the value from the Rainbow.color code inside the highlight callback. How would this be accomplished?
Author of marked here. I addressed this a while ago on the issue tracker: https://github.com/chjj/marked/issues/47
It's more than possible to use an asynchronous highlighter with marked. You'll just have to iterate over the tokens the lexer spits out.
Example here: https://github.com/chjj/marked/issues/47#issuecomment-5297067 (Keep in mind this is an example. You'll have to modify it a bit.)
I might just implement this natively in marked using the method in the link above. It will be a performance hit to the people using async highlighters, but if you need an async highlighter, that means the highlighter is doing some kind of IO and you're already taking a performance hit.
You could try using another highlighting library, such as highlight.js - It has synchronous highlighting methods (hljs.highlight(lang, code).value and hljs.highlightAuto(code).value) that you can use in the browser like this:
marked.setOptions({
highlight: function(code) {
return hljs.highlightAuto(code).value;
}
});
Here's a working JsFiddle example.
Unfortunately there's no way to solve the problem.
marked seems to require a synchronous syntax highlighter, and rainbow is an asynchronous syntax highlighter.
In Javascript there's no way to convert the latter to the former.
This is for example the reason why in node.js for many library functions there are both a synchronous and an asynchronous version. There's no way in Javascript to build a synchronous one given only the asynchronous one because you cannot create a "nested event loop" (in some cases the opposite conversion instead can be done using web workers).
May be it's not difficult to add the synchronous version to rainbow (e.g. by providing beforehand the external resources that it is probably loading asynchronously).
Not the perfect solution, but until the synchronous API has been merged into rainbow.js I solved it with the code below:
// ... after marked() has converted the markdown to html
// (the highlight option of marked should be unchanged!)
// find all <code> elements and go through each
$('body')
.find('code')
.each(function() {
var $code = $(this),
cls = $code.attr('class'),
language;
// no language information at all
if(typeof cls === 'undefined') {
return;
}
// actually we should also check if a valid "lang-" class
// (which is by default set through marked) is given
language = cls.split('-')[1];
// add the data-language to the <code> element
$code.data('language', language);
});
// let the rainbows shine
Rainbow.color();
This runs client side and uses jQuery.

Minimalistic example of IPython kernel javascript bi-directional communication

My goal is to write an interactive variable viewer for IPython, i.e. which allows one to see, say nested dicts/lists as a tree, and drill down (a bit like the console.log in Javascript).
I spent a lot of time trying to extract minimalistic code out of the directview example in IPython but still can't get my head around how it all works. My Python's ok but my jQuery experience is quite limited.
So I got to stripping down directview.js to the following
container.show();
var widget = $('<div/>')
element.append(widget);
var output = $('<div></div>');
$(widget).append(output)
var output_area = new IPython.OutputArea(output, false);
var callbacks = { 'output': $.proxy(output_area.handle_output, output_area) };
var code = 'print 1+1'
var msg_id = IPython.notebook.kernel.execute(code, callbacks, {silent: false});
This works when I load the directview.ipynb. However I am still not clear how to make it completely standalone (i.e. not require the directview.py, and pass another callback than the standard handle_output of IPython.OutputArea). One of the issues is the container.show() which fails when called in a standalone way.
I am lost on several aspects:
Why is there an element.append(widget) and then $(widget).append(output)? Also why is there also a need to create an Ipython.OutputArea. Isn't there a way to just create a <div id=my_output_area>blah</div> and then have the output callback fill it with the relevant data?
What's the whole .proxy thing about? I would like to create my own callback for output but when I do that and console.log() the arguments passed to the callback, they're undefined or just useless.
I appreciate that the authors of the IPython notebook have done an incredible job creating such a beautiful front-end using jQuery/websockets, and that creating developer documentation that allows beginners like me to tweak with it is asking much, but if anyone can lend a hand that would be great!
I can answer to your second question. The fact is when JavaScript calls your callback, it makes it so without specifying the context, i.e. without setting this (Pythonistas call it self). But it's possible to bound a function to this via $.proxy, which you saw in:
var callbacks = { 'output': $.proxy(output_area.handle_output, output_area) };

Override .load function of jQuery

I have site which uses $(selector).load(path) function in more than 300 pages. Now my client's requirement has changed and I need to access cross domain to call these pages.
For the purpose I have to replace all the .load( function to some cross-domain function with the help of YQL.
Is it possible to override my .load function and call prevent default and do my own code?
There is no clean way to do this, especially since $.fn.load does different things depending on the arguments and replacing it would affect all those subfunctions.
However, jQuery supports AJAX hooks which you might be able to achieve what you want.
In case all you need is support for IE's XDomainRequest, have a look at this plugin: https://github.com/jaubourg/ajaxHooks/blob/master/src/ajax/xdr.js
Anyway, if you really want to replace the ajax load function of jQuery, this code should do it:
var _load = $.fn.load;
$.fn.load = function(url, params, callback) {
if(typeof url !== "string") {
return _load.apply(this, arguments);
}
// do your ajax stuff here
}
This is exactly the same check jQuery uses to decide whether someone wants to bind the onload event or perform an AJAX load.
The most reasonnable way seems to me to not overload the jquery function but simply do a search and replace in your favorite editor to replace $(xxx).load( by yourpackage.load(xxx,.
This can be done in minutes even on 300 js files. Future changes will be easier and the code will be more readable as the reader never expects a jquery function to do something that isn't on the doc.
Yes, it's possible:
$.fn.load = yourFunc;
Is it recommended? I think not.

Categories