Attention

Version 3 is now the current version of MathJax. This document is for version 2.

Using Callbacks

A “callback” is a function that MathJax calls when it completes an action that may occur asynchronously (like loading a file). Many of MathJax’s functions operate asynchronously, and MathJax uses callbacks to allow you to synchronize your code with the action of those functions. The MathJax.Callback structure manages these callbacks. Callbacks can include not only a function to call, but also data to be passed to the function, and an object to act as the JavaScript this value in the resulting call (i.e., the object on which the callback is to execute).

Callbacks can be collected into Queues where the callbacks will be processed in order, with later callbacks waiting until previous ones have completed before they are called. They are also used with Signals as the means of receiving information about the signals as they occur.

A number of methods in MathJax.Hub and MathJax.Ajax accept callback specifications as arguments and return callback structures. These routines always will return a callback even when none was specified in the arguments, and in that case, the callback is a “do nothing” callback. The reason for this is so that the resulting callback can be used in a MathJax.Callback.Queue for synchronization purposes, so that the actions following it in the queue will not be performed until after the callback has been fired.

For example, the MathJax.Ajax.Require() method can be used to load external files, and it returns a callback that is called when the file has been loaded and executed. If you want to load several files and wait for them all to be loaded before performing some action, you can create a Queue into which you push the results of the MathJax.Ajax.Require() calls, and then push a callback for the action. The final action will not be performed until all the file-load callbacks (which precede it in the queue) have been called; i.e., the action will not occur until all the files are loaded.

Specifying a Callback

Callbacks can be specified in a number of different ways, depending on the functionality that is required of the callback. The easiest case is to simply provide a function to be called, but it is also possible to include data to pass to the function when it is called, and to specify the object that will be used as this when the function is called.

For example, the MathJax.Ajax.Require() method can accept a callback as its second argument (it will be called when the file given as the first argument is loaded and executed). So you can call

MathJax.Ajax.Require("[MathJax]/config/myConfig.js",function () {
  alert("My configuration file is loaded");
});

and an alert will appear when the file is loaded. An example of passing arguments to the callback function includes the following:

function loadHook (x) {alert("loadHook: "+x)}
MathJax.Ajax.Require("[MathJax]/config/myConfig.js",[loadHook,"myConfig"]);

Here, the loadHook() function accepts one argument and generates an alert that includes the value passed to it. The callback in the MathJax.Ajax.Require() call is [loadHook,"myConfig"], which means that (the equivalent of) loadHook("myConfig") will be performed when the file is loaded. The result should be an alert with the text loadHook: myConfig.

The callback for the MathJax.Ajax.Require() method actually gets called with a status value, in addition to any parameters already included in the callback specification, that indicates whether the file loaded successfully, or failed for some reason (perhaps the file couldn’t be found, or it failed to compile and run). So you could use

MathJax.Ajax.Require("[MathJax]/config/myConfig.js",function (status) {
  if (status === MathJax.Ajax.STATUS.OK) {
    alert("My configuration file is loaded");
  } else {
    alert("My configuration file failed to load!");
  }
});

to check if the file loaded properly. With additional parameters, the example might be

function loadHook (x,status) {alert("loadHook: "+x+" has status "+status)}
MathJax.Ajax.Require("[MathJax]/config/myConfig.js",[loadHook,"myConfig"]);

Note that the parameters given in the callback specification are used first, and then additional parameters from the call to the callback come afterward.

Callbacks to Object Methods

When you use a method of a JavaScript object, a special variable called this is defined that refers to the object whose method is being called. It allows you to access other methods or properties of the object without knowing explicitly where the object is stored.

For example,

var aPerson = {
  firstname: "John",
  lastname: "Smith",
  showName: function () {alert(this.firstname+" "+this.lastname)}
};

creates an object that contains three items, a firstname, and lastname, and a method that shows the person’s full name in an alert. So aPerson.showName() would cause an alert with the text John Smith to appear. Note, however that this only works if the method is called as aPerson.showName(); if instead you did

var f = aPerson.showName;  // assign f the function from aPerson
f();                       // and call the function

the association of the function with the data in aPerson is lost, and the alert will probably show undefined undefined. (In this case, f will be called with this set to the window variable, and so this.firstname and this.lastname will refer to undefined values.)

Because of this, it is difficult to use an object’s method as a callback if you refer to it as a function directly. For example,

var aFile = {
  name: "[MathJax]/config/myConfig.js",
  onload: function (status) {
    alert(this.name+" is loaded with status "+status);
  }
};

MathJax.Ajax.Require(aFile.name,aFile.onload);

would produce an alert indicating that “undefined” was loaded with a particular status. That is because aFile.onload is a reference to the onload method, which is just a function, and the association with the aFile object is lost. One could do

MathJax.Ajax.Require(aFile.name,function (status) {aFile.onload(status)});

but that seems needlessly verbose, and it produces a closure when one is not really needed. Instead, MathJax provides an alternative specification for a callback that allows you to specify both the method and the object it comes from:

MathJax.Ajax.Require(aFile.name,["onload",aFile]);

This requests that the callback should call aFile.onload as the function, which will maintain the connection between aFile and its method, thus preserving the correct value for this within the method.

As in the previous cases, you can pass parameters to the method as well by including them in the array that specifies the callback:

MathJax.Ajax.Require("filename",["method",object,arg1,arg2,...]);

This approach is useful when you are pushing a callback for one of MathJax’s Hub routines into the MathJax processing queue. For example,

MathJax.Hub.Queue(["Typeset",MathJax.Hub,"MathDiv"]);

pushes the equivalent of MathJax.Hub.Typeset("MathDiv") into the processing queue.

See the Callback Object reference pages for more information about the valid methods of specifying a callback.

Creating a Callback Explicitly

When you call a method that accepts a callback, you usually pass it a callback specification (like in the examples above), which describes a callback (the method will create the actual Callback object, and return that to you as its return value). You don’t usually create Callback objects directly yourself.

There are times, however, when you may wish to create a callback object for use with functions that don’t create callbacks for you. For example, the setTimeout() function can take a function as its argument, and you may want that function to be a method of an object, and would run into the problem described in the previous section if you simply passed the object’s method to setTimeout(). Or you might want to pass an argument to the function called by setTimeout(). (Altough the setTimeout() function can accept additional arguements that are supposed to be passed on to the code when it is called, some versions of Internet Explorer do not implement that feature, so you can’t rely on it.) You can use a Callback object to do this, and the MathJax.Callback() method will create one for you. For example,

function f(x) {alert("x = "+x)}
setTimeout(MathJax.Callback([f,"Hello World!"]),500);

would create a callback that calls f("Hello World!"), and schedules it to be called in half a second.