This is a syntax question I assume. Using function pointers is new to me, and required for a chunk of code I am working with. I want to pass some arguments to LoadResourceList to explain how to handle the data. LoadResourceList is a callback for when the ajaxObject has finished loading.
var getResourceList=new ajaxObject("resources.json",LoadResourceList); // Load Resource List
getResourceList.update();
You can pass the arguments for LoadResourceList into ajaxObject aswell:
function ajaxObject(json, callback) {
// code
if( typeof callback === 'function' ) {
var args = Array.prototype.slice.call(arguments, 2);
callback.apply(this, args);
}
}
Related
I'm trying to give my plugin callback functionality, and I'd like for it to operate in a somewhat traditional way:
myPlugin({options}, function() {
/* code to execute */
});
or
myPlugin({options}, anotherFunction());
How do I handle that parameter in the code? Is it treated as one full entity? I'm pretty sure I know where I'd place the executory code, but how do I get the code to execute? I can't seem to find a lot of literature on the topic.
Just execute the callback in the plugin:
$.fn.myPlugin = function(options, callback) {
if (typeof callback == 'function') { // make sure the callback is a function
callback.call(this); // brings the scope to the callback
}
};
You can also have the callback in the options object:
$.fn.myPlugin = function() {
// extend the options from pre-defined values:
var options = $.extend({
callback: function() {}
}, arguments[0] || {});
// call the callback and apply the scope:
options.callback.call(this);
};
Use it like this:
$('.elem').myPlugin({
callback: function() {
// some action
}
});
I don't know if I understand your question correctly. But for the second version: This would call anotherFunction immediately.
Basically your plugin should be some kind of function that looks like this:
var myPlugin = function(options, callback) {
//do something with options here
//call callback
if(callback) callback();
}
You have to provide a function object as callback, so either function(){...} or anotherFunction (without () ).
Bringing back a blast from the past.
Worth noting that if you have two arguments passed, for example:
$.fn.plugin = function(options, callback) { ... };
Then you call the plugin without the options argument but with a callback then you'll run into issues:
$(selector).plugin(function() {...});
I use this to make it a little more flexible:
if($.isFunction(options)) { callback = options }
I think this might help you
// Create closure.
(function( $ ) {
// This is the easiest way to have default options.
var settings = $.extend({
// These are the defaults.
onready: function(){},
//Rest of the Settings goes here...
}, options );
// Plugin definition.
$.fn.hilight = function( options ) {
//Here's the Callback
settings.onready.call(this);
//Your plugin code goes Here
};
// End of closure.
})( jQuery );
I had shared a article about Creating your Own jQuery Plugin.I think you should check that http://mycodingtricks.com/jquery/how-to-create-your-own-jquery-plugin/
Change your plugin function to take a second parameter. Assuming that the user passes a function, that parameter can be treated as a regular function.
Note that you can also make the callback a property of the options parameter.
For example:
$.fn.myPlugin = function(options, callback) {
...
if(callback) //If the caller supplied a callback
callback(someParam);
...
});
An example bit late, but it can be useful.
Using arguments can create the same functionality.
$.fn.myPlugin = function() {
var el = $(this[0]);
var args = arguments[0] || {};
var callBack = arguments[1];
.....
if (typeof callback == 'function') {
callback.call(this);
}
}
I have a nodejs code that has callback and I couldn't understand how it works. Can someone explain it
function readJSONIntoArray(directory, array, callback)
{
var ending = 'json';
fs.readdir(directory, function (err, files)
{
if (err)
throw err;
var fileCnt = files.length;
files.forEach(function (file)
{
if (endsWith(file, '.' + ending))
{
file = file.substring(0, file.length - (ending.length + 1));
var fileContent = require(path.join(directory, file));
array.push(fileContent);
log.info('Read file: ' + file);
}
fileCnt--;
if (fileCnt === 0 && typeof callback === 'function')
{
callback();
}
});
});
}
Here the callback is empty so I guess no value is being returned. But in actual output the array is returned. I couldn't understand an empty callback can return a array.
Function call:readJSONIntoArray(profilefolder, profiles, setProfileDescriptions);
Definition of setProfileDescriptions is separate.
function setProfileDescriptions()
{
profiles = bubblesort(profiles, 'order');
}
Inside the setProfileDescriptions the profile array is populated with the json data from the file read in the read function.
Can someone explain how the 3rd argument in the readJSONIntoArray function call is recognized as a function and the array profiles is returned?
You're right that readJSONIntoArray does't return anything in it's callback. Instead it appends new data to the second argument array, thus mutating it.
So, readJSONIntoArray was meant to be used in the following way:
var content = []; // empty array to accumulate data from readJSONIntoArray function
readJSONIntoArray('some directory', content, function () {
// content is full of data now
doSomething(content);
});
Though I must point out that this is not a common pattern in node.js, and that it should be avoided because it's too confusing.
In fact, there are several things in readJSONIntoArray implementation which were done wrong:
functions should never mutate their arguments;
async functions should not throw errors, they should return them in callback instead;
any data produced by the function should also be returned in callback.
var globalArray=[];
function readFunction(path,globalArray,callbackFunction){
globalArray.push(path);
callbackFunction();
}
function callbackFunction(){
//globalArray was global so i can call here
console.log(globalArray);
}
readFunction('filePath',globalArray,callbackFunction);
consider above code because the 'globalArray' declared as global i can access inside the callback function
function abc(arg1,arg2, callback){
console.log(arg1 + arg2) // I am doing something really interesting
if(callback){
callback(arg1+ arg2)
}
}
function add(){
console.log("from call back " + arguments[0])
}
var a =10;
abc(1,2, add)
this works fine, but if we need to send some additional arguments to the call back, what should we do??
Here, Apart from (arg1+ arg2) I need some other arguments to be set from the caller of abc to the callback
And, what is the difference between abc(1,2,add) and abc(1,2,add()) ??
Thanks :)
abc(1,2,add) => Giving the function argument as "function type". This is like giving a pointer to the function for later invoking it.
abc(1,2,add()) => Calling the add() function and giving its return value as argument.
Do you need that the callback support more than an argument? Since JavaScript is a dynamic language, just call the same callback function with more arguments:
callback(1,2,3,4)
callback(1,2,3,4,5)
callback(1,2,3,4,5,6).
JavaScript isn't strict with function signatures: functions have as many arguments as the caller gives to them.
For example, if you've a callback function like this:
function(a, b) {
}
And later you call it this way:
function("hello"); // Where's the second argument??
JavaScript won't complain. Simply b will be undefined.
the difference between add and add():
add is a function and add() is the return value of the function.
if you want to get more arguments of the function. use the arguments object
every function has an arguments object
arguments[0] == 1 arguments[1] == 2 arguments[2] == add.
You can call your callback with parameters from your original function and you can also provide the parameters for the callback inside your function call:
function f1 (args, callback, params) {
callback.apply(this, params); // Params needs to be an array
callback.apply(this, [args]); // This would call callback with 1 param - args
callback.call(this, args); // This is the same as the line above
}
function f2 () {
for (item in arguments) {
console.log(item);
}
}
f1('arg', f2, [1, 2, 3]);
If you call your function with a function call inside the parameters then it would immediately evaluate and it would not be executed as a callback.
The difference between abc(1,2,add) and abc(1,2,add()) is that in the second case, it's not abc that calls add. The consequence is that add executes much sooner than expected and without any arguments.
The usual way to pass extra parameters to a callback is to create an anonymous function that closes over the parameters:
var a=10;
var b=20;
abc(a, b, function(text){
add(a, b);
console.log(text); //logs "abc"
});
I would like a function 'get' that takes an id, an optional property parameter and a callback function. It would be used like so:
get(14297, 'name', function processName(name) {...});
get(14297, function processStudent(student) {...});
I have included one possible implementation below
function get(id, property, callback) {
var item = ...;
// property is callback
if (!callback) property(item);
// callback is callback
else callback(item[property])
}
It feels a little bit weird because
property(item);
Is actually a callback function depending on the context. Is there a better way to do this?
You should switch the parameters. Try this
function get(id, callback, property)
{
if(typeof property === "undefined")
callback(item);
else
callback(item[property]);
}
You can change the order of parameters, or test what the function is given to work out what they are. e.g.
function get(id, property, callback) {
if (arguments.length == 2) {
// second argument is callback
callback = property;
property = void 0;
}
...
}
or
function get(id, property, callback) {
if (typeof property == 'function') {
// second argument is callback
callback = property;
property = void 0;
}
...
}
and so on, but that type of overloading is not particularly liked.
This is the pattern used by jQuery:
function get(id, property, callback) {
// if the 2nd parameter is a function, assume that
// only two parameters were supplied
if (typeof property === 'function') {
callback = property;
property = undefined;
}
...
}
Effectively, if it sees unexpected parameter types it just shuffles their contents around until they match the alternative definition.
The arguments object is immutable. But you can slice it in an array, pop the last argument and deal with the other arguments as you normally would, since you know the callback argument isn't in it anymore.
Here is a way to do this:
function get() {
// Copy the `arguments` object in an array, since it's immutable
var args = Array.prototype.slice.call( arguments, 1 ),
// Pop the last argument of the arguments
callback = args.pop();
// Then deal with other arguments
// For example, check for the existence of the second argument
if ( args[1] ) {
}
// Then, you can call the callback function
callback();
}
How can I create a function, that will call another function, and when it completes, fire another callback function?
so existing functions are:
function f1(..) {..}
function myCallback() {...}
Now is it possible to make f1 fire and finish, THEN run myCallback()?
Provide a function reference as a parameter to the function you're calling.
function f1(fn) {
// ...
if (typeof fn === 'function') {
fn();
}
}
// can be a defined function name or a variable holding a reference to a function
f1(myCallback);
f1();
myCallback();
… unless f1 is asynchronous, in which case f1 would have to be edited to accept a callback and run it when it is finished. Since there are multiple things that could make a function asynchronous, it isn't possible to give a simple "…and this is how" answer without a lot more detail.
function f1(param1, callback){
// Do Work
callback();
}
function myCallback(){
// Do Callback Work
}
And then call f1 like:
f1(parameterValue, myCallback);
if f1 is just a simple javascript-function it runs synchonous, so you just have to call myCallback after it/at the end of f1. if if does some crazy ajax-stuff (with jquery in your case), there you can set a callback on these ajax-things.
You could create a facility to let you bind "onfinish" functions to any function:
function bindFollowup(f, followup) {
return function() {
f.apply(this, arguments);
followup && followup();
};
}
Then you can just define f1 and then write:
f1 = bindFollowup(f1, myCallback);
function f1(myCallBack)
{
// f1 activities
myCallBack();
}
lincolnk provided a great answer. It can be made much more flexible using the arguments array:
function f1() {
var i;
// ...
for (i = 0; i < arguments.length; ++i)
{
if (typeof arguments[i] === 'function')
{
arguments[i]();
}
}
}
Like this, you can pass in as many callback functions as you want. They will be executed in the order passed in. No harm is done if the argument is not a callback.
Finally, you can preserve the context and arguments of f1 using apply().
Preserving the context could definitely be useful in many situations. I'm not sure about the arguments, but it is an option.
function f1() {
var i;
// ...
for (i = 0; i < arguments.length; ++i)
{
if (typeof arguments[i] === 'function')
{
// You can leave off 'arguments', but preserving 'this' will
// often be useful.
arguments[i].apply(this, arguments);
}
}
}
the above allows you to do things like:
f1("alert me",function() {alert(arguments[0]);});
// Output when the call back is called:
// "alert me"
jsFiddle example