Azure Functions の JavaScript 開発者向けガイド

Azure Functions の JavaScript エクスペリエンスを利用すると、ランタイムと通信したり、バインディングを介してデータの送受信を行ったりする場合に context オブジェクトとして渡される関数を簡単にエクスポートできます。

この記事では、「 Azure Functions developer reference (Azure Functions 開発者向けリファレンス)」を既に読んでいることを前提としています。

関数のエクスポート

すべての JavaScript 関数では、ランタイムが関数を見つけて実行するために、module.exports を使用して function を 1 つエクスポートする必要があります。 この関数には、常に context オブジェクトを含める必要があります。

// 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 :)
};

direction === "in" のバインディングが関数の引数と一緒に渡されます。つまり、arguments を使用して、新しい入力を動的に処理できます (たとえば、arguments.length を使用して、すべての入力を繰り返し処理できます)。 この機能は、トリガーのみがあり、追加の入力がない場合に便利です。これは、context オブジェクトを参照しなくてもトリガーのデータに予測どおりにアクセスできるためです。

引数は、exports ステートメントで順序を指定していなくても、function.jsonに出現する順序で常に関数に渡されます。 たとえば、function(context, a, b) があり、それを function(context, a) に変更しても、arguments[3] を参照することで、関数コードの b の値を取得できます。

すべてのバインディングも、方向に関係なく、context オブジェクトと一緒に渡されます (以下のスクリプトを参照)。

context オブジェクト

ランタイムでは、context オブジェクトを使用して、関数との間でデータをやり取りし、ユーザーがランタイムと通信できるようにします。

context オブジェクトは、常に関数の最初のパラメーターとし、必ず含める必要があります。context オブジェクトには、ランタイムを適切に使用するために必要な context.donecontext.log などのメソッドが用意されているためです。 オブジェクトには、任意の名前 (ctxc など) を付けることができます。

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

context.bindings プロパティ

context.bindings

すべての入力データと出力データを含む名前付きオブジェクトを返します。 たとえば、function.json に次のバインディング定義が含まれている場合は、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 メソッド

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

コードが完了したことをランタイムに通知します。 ユーザーは context.done を呼び出す必要があります。そうしないと、ランタイムに関数の完了が通知されず、実行がタイムアウトになります。

context.done メソッドを使用すると、ユーザー定義のエラーに加えて、context.bindings オブジェクトのプロパティを上書きするプロパティのプロパティ バッグをランタイムに渡すことができます。

// 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 メソッド

context.log(message)

既定のトレース レベルでストリーミング コンソール ログに書き込むことができます。 context.log で利用可能な、他のトレース レベルでコンソール ログに書き込むことができるログ記録方法が他にあります。

メソッド Description
error(message) エラー レベルのログ、またはそれ以下に書き込みます。
warn(message) 警告レベルのログ、またはそれ以下に書き込みます。
info(message) 情報レベルのログ、またはそれ以下に書き込みます。
verbose(message) 詳細なレベルのログに書き込みます。

次の例は、警告トレース レベルでコンソールに書き込みます。

context.log.warn("Something has happened."); 

host.json ファイルにログを記録する場合のトレース レベルのしきい値を設定したり、それを無効にしたりできます。 ログに書き込む方法の詳細については、次のセクションを参照してください。

バインド データ型

入力バインドのデータ型を定義するには、バインド定義の dataType プロパティを使用します。 たとえば、バイナリ形式で HTTP 要求のコンテンツを読み取るには、binary 型を使用します。

{
    "type": "httpTrigger",
    "name": "req",
    "direction": "in",
    "dataType": "binary"
}

dataType のその他のオプションは、streamstring です。

トレース出力をコンソールに書き込む

関数で、context.log メソッドを使用してトレース出力をコンソールに書き込みます。 この時点では、console.log を使用してコンソールに書き込むことはできません。

context.log() を呼び出すと、既定のトレース レベルである、情報 トレース レベルでコンソールにメッセージが書き込まれます。 次のコードは、情報トレース レベルでコンソールに書き込みます。

context.log({hello: 'world'});  

上記のコードは次のコードと同等です。

context.log.info({hello: 'world'});  

次のコードは、エラー レベルでコンソールに書き込みます。

context.log.error("An error has occurred.");  

エラー は最高のトレース レベルであるため、ログ記録が有効になっている限り、このトレースはすべてのトレース レベルで出力に書き込まれます。

すべての context.log メソッドは、Node.js の util.format メソッドでサポートされているのと同じパラメーター形式をサポートしています。 既定のトレース レベルを使用してコンソールに出力する次のコードについて検討してください。

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

同じコードを次の形式で記述することもできます。

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

コンソール ログのトレース レベルを構成する

関数を使用して、コンソールに書き込むためのしきい値のトレース レベルを定義できます。これによって、関数からコンソールにトレースを書き込む方法を簡単に制御できます。 コンソールに書き込まれるすべてのトレースのしきい値を設定するには、host.json ファイルの tracing.consoleLevel プロパティを使用します。 この設定は、関数アプリのすべての関数に適用されます。 次の例では、詳細ログ記録が有効になるようにトレースのしきい値を設定します。

{ 
    "tracing": {      
        "consoleLevel": "verbose"     
    }
}  

consoleLevel の値は、context.log メソッドの名前に対応します。 コンソールへのすべてのトレース ログ記録を無効にするには、consoleLeveloff に設定します。 host.json ファイルの詳細については、host.json リファレンス トピックを参照してください。

HTTP トリガーとバインディング

HTTP、webhook トリガー、および HTTP 出力バインディングでは、要求オブジェクトと応答オブジェクトを使用して HTTP メッセージングを表します。

要求オブジェクト

request オブジェクトには、次のプロパティがあります。

プロパティ 説明
body 要求の本文を格納するオブジェクト。
headers 要求ヘッダーを格納するオブジェクト。
method 要求の HTTP メソッド。
originalUrl 要求の URL。
params 要求のルーティング パラメーターを格納するオブジェクト。
query クエリ パラメーターを格納するオブジェクト。
rawBody 文字列としてのメッセージの本文。

応答オブジェクト

response オブジェクトには、次のプロパティがあります。

プロパティ 説明
body 応答の本文を格納するオブジェクト。
headers 応答ヘッダーを格納するオブジェクト。
isRaw 応答の書式設定をスキップすることを示します。
状態 応答の HTTP 状態コード。

要求と応答へのアクセス

HTTP トリガーを使用する場合、HTTP 要求オブジェクトと応答オブジェクトにアクセスする方法は 3 つあります。

  • 名前付きの入力バインディングと出力バインディングから。 この方法で、HTTP トリガーとバインディングは他のバインディングと同じように動作します。 次の例では、名前付き response バインディングを使用して、応答オブジェクトを設定します。

    context.bindings.response = { status: 201, body: "Insert succeeded." };
    
  • context オブジェクトの req プロパティと res プロパティから。 この方法で、完全な context.bindings.name パターンを使用する代わりに、従来のパターンを使用して context オブジェクトから HTTP データにアクセスできます。 次の例では、contextreq オブジェクトと res オブジェクトにアクセスする方法を示します。

    // You can access your http request off 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!' }; 
    
  • context.done() の呼び出しで。 これは、context.done() メソッドに渡される応答を返す特殊な種類の HTTP バインディングです。 次の HTTP 出力バインディングで、$return 出力パラメーターを定義します。

    {
      "type": "http",
      "direction": "out",
      "name": "$return"
    }
    

    この出力バインディングでは、次のように done() を呼び出すときにユーザーに応答を返すことを想定しています。

     // Define a valid response object.
    res = { status: 201, body: "Insert succeeded." };
    context.done(null, res);   
    

Node のバージョンとパッケージの管理

Node のバージョンは、現在、 6.5.0にロックされています。 現在、さまざまなバージョンのサポートを追加して構成できるようにするために、調査しています。

次の手順で、関数アプリにパッケージを含めることができます。

  1. https://<function_app_name>.scm.azurewebsites.net にアクセスします。

  2. [デバッグ コンソール] > [CMD] をクリックします。

  3. D:\home\site\wwwroot に移動し、ページの上半分にある wwwroot フォルダーに package.json ファイルをドラッグします。
    関数アプリにファイルをアップロードする方法は、他にもあります。 詳細については、「関数アプリ ファイルを更新する方法」を参照してください。

  4. package.json ファイルがアップロードされたら、Kudu リモート実行コンソールnpm install コマンドを実行します。
    この操作によって、package.json ファイルに示されているパッケージがダウンロードされ、関数アプリが再起動されます。

必要なパッケージがインストールされたら、次の例に示すように 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'});

関数アプリのルートに package.json ファイルを定義する必要があります。 このファイルを定義することによって、アプリのすべての関数を同じキャッシュされたパッケージで共有し、最高クラスのパフォーマンスを得ることができます。 バージョンの競合がある場合は、個別の関数のフォルダーに package.json ファイルを追加することで競合を解決できます。

環境変数

環境変数またはアプリ設定値を取得するには、次のコード例のように、 process.envを使用します。

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];
}

JavaScript 関数に関する考慮事項

JavaScript 関数を使用するときは、以下の 2 つのセクションに記載されている事柄に注意する必要があります。

シングルコア App Service プランを選択する

App Service プランを使用する関数アプリを作成するときは、複数のコアを持つプランではなく、シングルコア プランを選択することをお勧めします。 今日では、関数を使用して、シングルコア VM で JavaScript 関数をより効率的に実行できるようになりました。そのため、大規模な VM を使用しても、期待以上にパフォーマンスが向上することはありません。 必要な場合は、シングルコア VM インスタンスを追加することで手動でスケールアウトするか、自動スケールを有効にすることができます。 詳細については、「手動または自動によるインスタンス数のスケール変更」を参照してください。

TypeScript と CoffeeScript のサポート

ランタイムによる TypeScript/CoffeeScript の自動コンパイルはまだ直接サポートされていません。そのため、デプロイ時にランタイムの外部ですべて処理する必要があります。

次のステップ

詳細については、次のリソースを参照してください。