I just stepped on this bug (or maybe it's a "feature")
If I pass a bound method (defined with fat arrow) as a D3js callback, it gets called with null arguments:
d3.json "some.json", #handler
If I enclose it in a bound closure (fat arrow) then it receives its arguments ok:
d3.json "some.json", (json) => #handler json
Here is a JSFiddle showing the issue.
Passing fat-arrow bound methods as standard Javascript callbacks (eg. to setTimeout) or as jQuery callbacks or event handlers is a proven technique, in fact I have an entire application written this way.
Why is it not working in D3js?
The issue is that the callback for d3.json has two arguments (see the documentation):
[T]he callback is invoked with two arguments: the error, if any, and the parsed JSON.
If D3 detects that the callback function has only one argument, it only passes the data, but it can't do that in your first example. Changing the definition of the handler function accordingly fixes the issue:
directHandler: (e, x) =>
#log "directHandler received #{JSON.stringify x}"
Complete demo here.
Related
Both promises and AJAX calls are asynchronous operations. A GET/POST request could be made with both. << Edit: that's a WRONG statement
So what's the difference between them? And when would be best to use one instead of the other?
Also, one more thing:
Recently I encountered a promise which had an AJAX in its body. Why put an async operation inside an async operation? That's like putting a bread loaf in a bread sandwich.
function threadsGet() {
return new Promise((resolve, reject) => {
$.getJSON('api/threads')
.done(resolve)
.fail(reject);
})
}
jQuery is used here. And the AJAX call has Promise behavior and properties. I didn't get that earlier but here are my thoughts:
We can do something in the Promise. Then use the AJAX call and in the done function pass the resolved Promise logic. Specifically in this example there is none.
Now I see that I had confused both. They're pretty much 2 different things. Just because they're asynchronous, doesn't mean they're interchangeable.
==============
EDIT 2: Just some materials I found useful:
Promise Anti-Patterns
You are confused about promises and Ajax calls. They are kind of like apples and knives. You can cut an apple with knife and the knife is a tool that can be applied to an apple, but the two are very different things.
Promises are a tool for managing asynchronous operations. They keep track of when asynchronous operations complete and what their results are and let you coordinate that completion and those results (including error conditions) with other code or other asynchronous operations. They aren't actually asynchronous operations in themselves. An Ajax call is a specific asynchronous operation that can be used with with a traditional callback interface or wrapped in a promise interface.
So what's the difference between them? And when would be best to use
one instead of the other?
An Ajax call is a specific type of asynchronous operation. You can make an Ajax call either with a traditional callback using the XMLHttpRequest interface or you can make an Ajax call (in modern browsers), using a promise with the fetch() interface.
Recently I encountered a promise which had an AJAX in its body. Why
put an async operation inside an async operation? That's like putting
a bread loaf in a bread sandwich.
You didn't show the specific code you were talking about, but sometimes you want to start async operation 1 and then when that async operation is done, you want to them start async operation 2 (often using the results of the first one). In that case, you will typically nest one inside the other.
Your code example here:
function threadsGet() {
return new Promise((resolve, reject) => {
$.getJSON('api/threads')
.done(resolve)
.fail(reject);
})
}
is considered a promise anti-pattern. There's no reason to create a new promise here because $.getJSON() already returns a promise which you can return. You can just do this instead:
function threadsGet() {
return $.getJSON('api/threads');
}
Or, if you want to "cast" the somewhat non-standard jQuery promise to a standard promise, you can do this:
function threadsGet() {
return Promise.resolve($.getJSON('api/threads'));
}
I'm looking at the
documentation
for triggering events in OpenLayers. It lists triggerEvent as taking in a type:String argument and a evt:Event argument. I understand what the type parameter is, but what object is the Event object? I can't find a clear example.
If it is relevant, I am working on an interface between Google Maps v3 and OpenLayers, and I'm trying to come up with a way so that I can have a the same API interface to calls to:
google.maps.event.trigger(instance:Object, eventName:String, var_args:*)
openLayersObj.events.triggerEvent(type:String, evt:Event)
Doc is wrong. It should be Event || object. Object that will be args passed to the listeners callback.
Look at the source: https://github.com/openlayers/openlayers/blob/master/lib/OpenLayers/Events.js#L820
Example of use: https://github.com/openlayers/openlayers/blob/master/lib/OpenLayers/Map.js#L1042
I have developed some websites and I always stumble a the same point: multiple ajax calls. I have a main page where all the content is loaded asynchronously. When the page is loaded, there are four INDEPENDENT calls that "draw" the page by areas (top, left, right and bottom) and while it is loaded I show to the user the typical ajax spins. So, when a request is received by the browser I execute the callback and the different areas are drawing at different time. The fact is that the answer for the server sometimes are mixed up, I mean, the answer of top is drawn in the left or vice-versa.
I've tried some solutions like creating a timestamp in each request to indicate to the browser and server that each request is different.
Also I've tried to configure some parameters of cache in the server, in case.
The only way in which works has been including the request2 in the callback of the one, etc.
Anyone knows the proper way to do it or ever has beaten this issue?? I don't want to do chained request.
Thanks
Here is an example of what I mean:
$(document).ready(function() {
$.get('/activity',Common.genSafeId(),function(data){$('#stream').html(data);$("#load_activity").addClass("empty");});
$.get('/messages',Common.genSafeId(),function(data){$('#message').html(data);$("#load_messages").addClass("empty");});
$.get('/deals',Common.genSafeId(),function(data){$('#new_deals_container').html(data);$("#load_deal").addClass("empty");});
$.get('/tasks',Common.genSafeId(),function(data){$('#task_frames').html(data);$("#load_task").addClass("empty");});});
And the html is a simple jsp with four container each one with a different id.
CLOSURES
Closures are a little mind-blowing at first. They are a feature of javaScript and several other modern computing languages.
A closure is formed by an executed instance of a function that has an inner function (typically an anonymous event handler or named method) that needs access to one or more outer variables (ie. variables that are within the outer function but outside the inner function). The mind-blowing thing is that the inner function retains access to the outer variables even though the outer function has completed and returned at the time that the inner function executes!
Moreover, variables trapped by a closure are accessible only to inner functions and not to the further-out environment that brought the closure into being. This feature allows us, for example, to create class-like structures with private as well as public members even in the absence of language keywords "Public" and "Private".
Closures are made possible by inner functions' use of outer variables suppressing javaScript's "garbage collection" which would otherwise destroy the outer function's environment at some indeterminate point after completion.
The importance of closures to good, tidy javaScript programming cannot be overstressed.
In the code below the function getData() forms, at each call, a closure trapping id1 and id2 (and url), which remain available to the anonymous ajax response handler ($.get's third argument).
$(document).ready(function() {
function getData(url, id1, id2) {
$.get(url, Common.genSafeId(), function(data) {
$(id1).html(data);
$(id2).addClass("empty");
});
}
getData('/activity', '#stream', '#load_activity');
getData('/messages', '#message', '#load_messages');
getData('/deals', '#new_deals_container', '#load_deal');
getData('/tasks', '#task_frames', '#load_task');
});
Thus, rather than writing four separate handlers, we exploit the language's ability to form closures and call the same function, getData(), four times. At each call, getData() forms a new closure which allows $.get's response handler (which is called asynchronously when the server responds) to address its DOM elements.
Make sure you have different callbacks for each ajax call, it sounds like you are trying to use the same function for all four, thus when they are called out of order (because they take different amounts of time server-side), they are rendering in the wrong place. If you insist on using the same function for all your callbacks, then you have to put something in the payload so that the callback knows where to render to.
I'm trying to programmatically create a click event in MATLAB that will mimic the user clicking on a GUI object. The callback function for the object is a subfunction, so I can't call it directly. However, I am able to get the callback property from the object, which ends up being a 3-by-1 cell array with the following contents:
#uiBlockFn/callback_til [ 188.0011] [1x1 struct]
How can I invoke this callback function in code such that it mimics what would happen when a user clicks the GUI object?
Let's say you have a graphics object with handle hObject, and you got the callback for the object like so:
callbackCell = get(hObject,'Callback');
As you mentioned, the cell array callbackCell that you get ends up being a 3 element cell array with a function handle in the first cell and other data in the other two cells. When the callback for an object is defined as a cell array (like it is in your case), the callback function handle (or string name) is stored in the first cell and additional input arguments you want passed to the callback function are in the remaining cells.
However, when this callback is invoked when the object is activated, there will actually be 2 additional arguments automatically inserted by MATLAB at the beginning of the input argument list. These are:
hObject: The handle to the object whose callback is now being called.
eventData: A structure of data related to the user-activated event, which is often just the empty matrix [] (except in a few cases).
So, if you want to mimic the action of the object being activated by the user, you would want to invoke your callback function as follows (assuming there is no event data needed):
callbackCell{1}(hObject,[],callbackCell{2:end});
This is what the built-in hgfeval function is for:
http://undocumentedmatlab.com/blog/hgfeval/
I'm trying to programmatically create a click event in MATLAB that will mimic the user clicking on a GUI object. The callback function for the object is a subfunction, so I can't call it directly. However, I am able to get the callback property from the object, which ends up being a 3-by-1 cell array with the following contents:
#uiBlockFn/callback_til [ 188.0011] [1x1 struct]
How can I invoke this callback function in code such that it mimics what would happen when a user clicks the GUI object?
Let's say you have a graphics object with handle hObject, and you got the callback for the object like so:
callbackCell = get(hObject,'Callback');
As you mentioned, the cell array callbackCell that you get ends up being a 3 element cell array with a function handle in the first cell and other data in the other two cells. When the callback for an object is defined as a cell array (like it is in your case), the callback function handle (or string name) is stored in the first cell and additional input arguments you want passed to the callback function are in the remaining cells.
However, when this callback is invoked when the object is activated, there will actually be 2 additional arguments automatically inserted by MATLAB at the beginning of the input argument list. These are:
hObject: The handle to the object whose callback is now being called.
eventData: A structure of data related to the user-activated event, which is often just the empty matrix [] (except in a few cases).
So, if you want to mimic the action of the object being activated by the user, you would want to invoke your callback function as follows (assuming there is no event data needed):
callbackCell{1}(hObject,[],callbackCell{2:end});
This is what the built-in hgfeval function is for:
http://undocumentedmatlab.com/blog/hgfeval/