Azure Functions JavaScript developer guide

The JavaScript experience for Azure Functions makes it easy to export a function which is passed a context object for communicating with the runtime, and for receiving and sending data via bindings.

This article assumes that you've already read the Azure Functions developer reference.

Exporting a function

All JavaScript functions must export a single function via module.exports for the runtime to find the function and run it. This function must always include a context object.

// You must include a context, but other arguments are optional
module.exports = function(context) {
    // Additional inputs can be accessed by the arguments property
    if(arguments.length === 4) {
        context.log('This function has 4 inputs');
    }
};
// or you can include additional inputs in your arguments
module.exports = function(context, myTrigger, myInput, myOtherInput) {
    // function logic goes here :)
};

Bindings of direction === "in" are passed along as function arguments, meaning you can use arguments to dynamically handle new inputs (for example, by using arguments.length to iterate over all your inputs). This functionality is very convenient if you only have a trigger with no additional inputs, as you can predictably access your trigger data without referencing your context object.

The arguments are always passed along to the function in the order they occur in function.json, even if you don't specify them in your exports statement. For example, if you have function(context, a, b) and change it to function(context, a), you can still get the value of b in function code by referring to arguments[3].

All bindings, regardless of direction, are also passed along on the context object (see below).

context object

The runtime uses a context object to pass data to and from your function and to let you communicate with the runtime.

The context object is always the first parameter to a function and should always be included because it has methods such as context.done and context.log which are required to correctly use the runtime. You can name the object whatever you like (i.e. ctx or c).

// You must include a context, but other arguments are optional
module.exports = function(context) {
    // function logic goes here :)
};

context.bindings

The context.bindings object collects all your input and output data. The data is added onto the context.bindings object via the name property of the binding. For instance, given the following binding definition in function.json, you can access the contents of the queue via context.bindings.myInput.

{
    "type":"queue",
    "direction":"in",
    "name":"myInput"
    ...
}
// myInput contains the input data which may have properties such as "name"
var author = context.bindings.myInput.name;
// Similarly, you can set your output data
context.bindings.myOutput = { 
        some_text: 'hello world', 
        a_number: 1 };

context.done([err],[propertyBag])

The context.done function tells the runtime that you're done running. This is important to call when you're done with the function; if you don't, the runtime will still never know that your function completed.

The context.done function allows you to pass back a user-defined error to the runtime, as well as a property bag of properties which will overwrite the properties on the context.bindings object.

// Even though we set myOutput to have:
//  -> text: hello world, number: 123
context.bindings.myOutput = { text: 'hello world', number: 123 };
// If we pass an object to the done function...
context.done(null, { myOutput: { text: 'hello there, world', noNumber: true }});
// the done method will overwrite the myOutput binding to be: 
//  -> text: hello there, world, noNumber: true

context.log(message)

The context.log method allows you to output log statements that are correlated together for logging purposes. If you use console.log, your messages will only show for process level logging, which isn't as useful.

/* You can use context.log to log output specific to this 
function. You can access your bindings via context.bindings */
context.log({hello: 'world'}); // logs: { 'hello': 'world' } 

The context.log method supports the same parameter format that the Node util.format method supports. So, for example, code like this:

context.log('Node.js HTTP trigger function processed a request. RequestUri=' + req.originalUrl);
context.log('Request Headers = ' + JSON.stringify(req.headers));

can be written like this:

context.log('Node.js HTTP trigger function processed a request. RequestUri=%s', req.originalUrl);
context.log('Request Headers = ', JSON.stringify(req.headers));

HTTP triggers: context.req and context.res

In the case of HTTP Triggers, because it is such a common pattern to use req and res for the HTTP request and response objects, we decided to make it easy to access those on the context object, instead of forcing you to use the full context.bindings.name pattern.

// You can access your http request off of the context ...
if(context.req.body.emoji === ':pizza:') context.log('Yay!');
// and also set your http response
context.res = { status: 202, body: 'You successfully ordered more coffee!' };   

Node Version & Package Management

The node version is currently locked at 6.5.0. We're investigating adding support for more versions and making it configurable.

You can include packages in your function by uploading a package.json file to your function's folder in the function app's file system. For file upload instructions, see the How to update function app files section of the Azure Functions developer reference topic.

You can also use npm install in the function app's SCM (Kudu) command line interface:

  1. Navigate to: https://<function_app_name>.scm.azurewebsites.net.
  2. Click Debug Console > CMD.
  3. Navigate to D:\home\site\wwwroot\<function_name>.
  4. Run npm install.

Once the packages you need are installed, you import them to your function in the usual ways (i.e. via require('packagename'))

// Import the underscore.js library
var _ = require('underscore');
var version = process.version; // version === 'v6.5.0'

module.exports = function(context) {
    // Using our imported underscore.js library
    var matched_names = _
        .where(context.bindings.myInput.names, {first: 'Carla'});

Node should have a package.json at the root of the Function App so Functions can shared cached packages. If there are version conflicts, you can add a package.json at a Function level. However, doing so should be avoided for performance reasons.

Environment variables

To get an environment variable or an app setting value, use process.env, as shown in the following code example:

module.exports = function (context, myTimer) {
    var timeStamp = new Date().toISOString();

    context.log('Node.js timer trigger function ran!', timeStamp);   
    context.log(GetEnvironmentVariable("AzureWebJobsStorage"));
    context.log(GetEnvironmentVariable("WEBSITE_SITE_NAME"));

    context.done();
};

function GetEnvironmentVariable(name)
{
    return name + ": " + process.env[name];
}

TypeScript/CoffeeScript support

There isn't, yet, any direct support for auto-compiling TypeScript/CoffeeScript via the runtime, so that would all need to be handled outside the runtime, at deployment time.

Next steps

For more information, see the following resources: