Panduan Azure Functions untuk pengembang JavaScript

Panduan ini berisi informasi terperinci untuk membantu Anda mengembangkan Azure Functions menggunakan JavaScript dengan baik.

jika Anda pengembang Express.js, Node.js, atau JavaScript yang baru menggunakan Azure Functions, bacalah terlebih dahulu salah satu artikel berikut ini:

Memulai Konsep Pembelajaran terpandu

Dasar-dasar fungsi JavaScript

Fungsi JavaScript (Node.js) adalah hasil ekspor function yang berjalan saat dipicu (pemicu dikonfigurasi di function.json). Argumen pertama yang diteruskan ke setiap fungsi adalah objek context, yang digunakan untuk menerima dan mengirim pengikatan data, membuat log, dan berkomunikasi dengan runtime.

Struktur folder

Struktur folder yang diperlukan untuk proyek JavaScript terlihat seperti berikut ini. Tampilan default ini bisa diubah. Untuk informasi selengkapnya, lihat bagian scriptFile di bawah ini.

FunctionsProject
 | - MyFirstFunction
 | | - index.js
 | | - function.json
 | - MySecondFunction
 | | - index.js
 | | - function.json
 | - SharedCode
 | | - myFirstHelperFunction.js
 | | - mySecondHelperFunction.js
 | - node_modules
 | - host.json
 | - package.json
 | - extensions.csproj

Di akar proyek, terdapat file host.json bersama yang dapat digunakan untuk mengonfigurasi aplikasi fungsi. Setiap fungsi memiliki folder dengan file kode sendiri (.js) dan file konfigurasi pengikatan (function.json). Nama direktori induk function.json selalu merupakan nama fungsi Anda.

Ekstensi pengikatan yang diperlukan dalam versi 2.x dari runtime Functions didefinisikan dalam file extensions.csproj, dengan file pustaka aktual di folder bin. Saat mengembangkan secara lokal, Anda harus mendaftarkan ekstensi pengikatan. Saat mengembangkan fungsi di portal Microsoft Azure, pendaftaran ini dilakukan untuk Anda.

Mengekspor fungsi

Fungsi JavaScript harus diekspor melalui module.exports (atau exports). Fungsi yang diekspor harus merupakan fungsi JavaScript yang berjalan saat dipicu.

Secara default, runtime Functions mencari fungsi Anda di index.js, tempat index.js berbagi direktori induk yang sama dengan function.json yang sesuai. Dalam kasus default, fungsi yang diekspor harus menjadi satu-satunya ekspor dari filenya atau dari ekspor bernama run atau index. Untuk mengonfigurasi lokasi file dan mengekspor nama fungsi Anda, pelajari tentang mengonfigurasi titik masuk fungsi Anda di bawah ini.

Fungsi yang diekspor diberikan sejumlah argumen saat eksekusi. Argumen pertama yang diperlukan selalu merupakan objek context.

Saat menggunakan deklarasi async function atau Janji JavaScript biasa di versi 2.x, 3.x, atau 4.x dari runtime Functions, Anda tidak perlu melakukan panggilan balik context.done secara eksplisit untuk memberi sinyal bahwa fungsi telah selesai. Fungsi Anda akan lengkap ketika fungsi/Promise asinkron yang diekspor selesai.

Contoh berikut adalah fungsi sederhana yang mencatat bahwa fungsi telah terpicu dan segera menyelesaikan eksekusi.

module.exports = async function (context) {
    context.log('JavaScript trigger function processed a request.');
};

Saat mengekspor fungsi asinkron, Anda juga dapat mengonfigurasi pengikatan output untuk mengambil nilai return. Hal tersebut disarankan bila Anda hanya memiliki satu pengikatan output.

Mengembalikan dari fungsi

Untuk menetapkan output menggunakan return, ubah properti name menjadi $return di function.json.

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

Dalam hal ini, fungsi Anda akan terlihat seperti contoh berikut:

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    // You can call and await an async method here
    return {
        body: "Hello, world!"
    };
}

Pengikatan

Di JavaScript, pengikatan dikonfigurasi dan didefinisikan dalam fungsi function.json. Fungsi berinteraksi dengan pengikatan dengan berbagai cara.

Input

Input dibagi menjadi dua kategori di Azure Functions: pertama adalah input pemicu dan kedua adalah input tambahan. Pemicu dan pengikatan input lainnya (pengikatan direction === "in") dapat dibaca oleh fungsi dengan tiga cara:

  • [Disarankan] Sebagai parameter yang diteruskan ke fungsi Anda. Parameter diteruskan ke fungsi dalam urutan yang sama saat mereka didefinisikan di function.json. Properti name yang didefinisikan di function.json tidak harus cocok dengan nama parameter Anda, meskipun seharusnya begitu.

    module.exports = async function(context, myTrigger, myInput, myOtherInput) { ... };
    
  • Sebagai anggota objek context.bindings. Setiap anggota dinamai oleh properti name yang didefinisikan dalam function.json.

    module.exports = async function(context) { 
        context.log("This is myTrigger: " + context.bindings.myTrigger);
        context.log("This is myInput: " + context.bindings.myInput);
        context.log("This is myOtherInput: " + context.bindings.myOtherInput);
    };
    

Output

Output (pengikatan direction === "out") dapat ditulis oleh satu fungsi dengan beberapa cara. Dalam semua kasus, properti name pengikatan sebagaimana didefinisikan difunction.json sesuai dengan nama anggota objek yang ditulis dalam fungsi Anda.

Anda dapat menetapkan data ke pengikatan output dengan salah satu cara berikut (jangan gabungkan metode ini):

  • [Direkomendasikan untuk beberapa output] Mengembalikan objek. Jika Anda menggunakan fungsi pengembalian asinkron/Promise, Anda dapat mengembalikan objek dengan data output yang ditetapkan. Dalam contoh di bawah ini, pengikatan output diberi nama "httpResponse" dan "queueOutput" function.json.

    module.exports = async function(context) {
        let retMsg = 'Hello, world!';
        return {
            httpResponse: {
                body: retMsg
            },
            queueOutput: retMsg
        };
    };
    
  • [Disarankan untuk output tunggal] Mengembalikan nilai secara langsung dan menggunakan nama pengikatan $return. Ini hanya berlaku untuk fungsi pengembalian asinkron/Promise. Lihat contoh mengekspor fungsi asinkron.

  • Menetapkan nilai ke context.bindings Anda dapat menetapkan nilai secara langsung ke pengikatan konteks.

    module.exports = async function(context) {
        let retMsg = 'Hello, world!';
        context.bindings.httpResponse = {
            body: retMsg
        };
        context.bindings.queueOutput = retMsg;
    };
    

Jenis data pengikatan

Untuk menentukan jenis data untuk pengikatan input, gunakan properti dataType di definisi pengikatan. Misalnya, untuk membaca konten permintaan HTTP dalam format biner, gunakan tipe binary:

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

Pilihan untuk dataType adalah: binary, stream, dan string.

objek konteks

Runtime menggunakan objek context untuk meneruskan data ke dan dari fungsi dan runtime Anda. Berfungsi untuk membaca dan mengatur data dari pengikatan dan untuk menulis ke log, objek context selalu menjadi parameter pertama yang diteruskan ke fungsi.

module.exports = async function(context){

    // function logic goes here

    context.log("The function has executed.");
};

Konteks yang diteruskan ke fungsi Anda mengekspos properti executionContext, yang merupakan objek dengan properti berikut:

Nama properti Jenis Deskripsi
invocationId String Menyediakan pengenal unik untuk pemanggilan fungsi tertentu.
functionName String Menyediakan nama fungsi yang sedang berjalan
functionDirectory String Menyediakan direktori aplikasi fungsi.

Contoh berikut menunjukkan cara mengembalikan invocationId.

module.exports = async function (context, req) {
    context.res = {
        body: context.executionContext.invocationId
    };
};

properti context.bindings

context.bindings

Mengembalikan objek bernama yang digunakan untuk membaca atau menetapkan data yang mengikat. Input dan ikatan data pemicu dapat diakses dengan membaca properti di context.bindings. Ikatan data output dapat ditetapkan dengan menambahkan data ke context.bindings

Misalnya, definisi ikatan di function.json berikut ini mengizinkan Anda mengakses isi antrean dari context.bindings.myInput dan menetapkan output ke antrean menggunakan context.bindings.myOutput.

{
    "type":"queue",
    "direction":"in",
    "name":"myInput"
    ...
},
{
    "type":"queue",
    "direction":"out",
    "name":"myOutput"
    ...
}
// 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 };

Dalam fungsi sinkron, Anda dapat memilih untuk menentukan data pengikatan output menggunakan metode context.done, bukan objek context.binding (lihat di bawah).

properti context.bindingData

context.bindingData

Mengembalikan objek bernama yang berisi metadata pemicu dan data pemanggilan fungsi (invocationId, sys.methodName, sys.utcNow, sys.randGuid). Untuk contoh metadata pemicu, lihat contoh hub kejadian ini.

metode context.done

Dalam 2.x, 3.x, dan 4.x, fungsi harus ditandai sebagai asinkron meskipun tidak ada panggilan fungsi yang ditunggu di dalam fungsi, dan fungsi tersebut tidak perlu memanggil context.done untuk menunjukkan bahwa fungsi berakhir.

//you don't need an awaited function call inside to use async
module.exports = async function (context, req) {
    context.log("you don't need an awaited function call inside to use async")
};

metode context.log

context.log(message)

Memungkinkan Anda menulis ke log fungsi streaming pada tingkat pelacakan default, dengan tingkatan pencatatan lain yang tersedia. Pembuatan log pelacakan dijelaskan secara rinci di bagian berikutnya.

Menulis jejak output ke log

Di Functions, gunakan metode context.log untuk menulis output jejak ke log dan konsol. Saat Anda memanggil context.log(), pesan Anda ditulis ke log di tingkat pelacakan default, yang merupakan info tingkat pelacakan. Fungsi terintegrasi dengan Azure Application Insights untuk menangkap log aplikasi fungsi Anda dengan lebih baik. Application Insights adalah bagian dari Azure Monitor yang menyediakan fasilitas untuk pengumpulan, penyajian visual, dan analisis telemetri aplikasi dan output pelacakan Anda. Untuk mempelajari selengkapnya, lihat memantau Azure Functions.

Contoh berikut menulis log di tingkat pelacakan info, termasuk ID pemanggilan:

context.log("Something has happened. " + context.invocationId); 

Semua metode context.log mendukung format parameter yang sama, yang didukung oleh Node.js metode util.format. Pertimbangkan kode berikut, yang menulis log fungsi menggunakan tingkat pelacakan default:

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

Anda juga dapat menulis kode yang sama dalam format berikut:

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

Catatan

Jangan gunakan console.log untuk menulis output pelacakan. Karena output dari console.log diambil pada tingkat aplikasi fungsi, output tidak terikat dengan pemanggilan fungsi tertentu dan tidak ditampilkan dalam log fungsi tertentu. Selain itu, runtime Functions versi 1.x tidak mendukung penggunaan console.log untuk menulis ke konsol.

Tingkatan pelacakan

Selain tingkat default, metode pembuatan log berikut tersedia untuk mengizinkan Anda menulis log fungsi pada tingkat pelacakan tertentu.

Metode Deskripsi
context.log.error(pesan) Menulis peristiwa tingkat kesalahan ke log.
context.log.warn(pesan) Menulis peristiwa tingkat peringatan ke log.
context.log.info(pesan) Menulis ke pencatatan tingkat info, atau yang lebih rendah.
context.log.verbose(pesan) Menulis ke pengelogan tingkat verbose.

Contoh berikut menulis log yang sama pada tingkat pelacakan peringatan, alih-alih tingkat info:

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

Karena kesalahan adalah tingkat pelacakan tertinggi, jejak ini ditulis ke output di semua tingkat pelacakan selama pengelogan diaktifkan.

Mengonfigurasi tingkat pelacakan untuk pembuatan log

Fungsi memungkinkan Anda menentukan tingkat pelacakan ambang batas untuk menulis ke log atau konsol. Pengaturan ambang batas tertentu bergantung pada versi runtime Functions Anda.

Untuk mengatur ambang batas untuk pelacakan yang ditulis ke log, gunakan properti logging.logLevel di file host.json. Objek JSON ini mengizinkan Anda menentukan ambang batas default untuk semua fungsi di aplikasi fungsi Anda, serta menentukan ambang batas tertentu untuk fungsi individual. Untuk mempelajari selengkapnya, lihat Cara mengonfigurasi pemantauan untuk Azure Functions.

Log telemetri kustom

Secara default, Functions menulis output sebagai jejak ke Application Insights. Untuk kontrol lebih lanjut, gunakan Aplikasi Insights Node.js SDK untuk mengirim data telemetri kustom ke instans Application Insights Anda.

const appInsights = require("applicationinsights");
appInsights.setup();
const client = appInsights.defaultClient;

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    // Use this with 'tagOverrides' to correlate custom telemetry to the parent function invocation.
    var operationIdOverride = {"ai.operation.id":context.traceContext.traceparent};

    client.trackEvent({name: "my custom event", tagOverrides:operationIdOverride, properties: {customProperty2: "custom property value"}});
    client.trackException({exception: new Error("handled exceptions can be logged with this method"), tagOverrides:operationIdOverride});
    client.trackMetric({name: "custom metric", value: 3, tagOverrides:operationIdOverride});
    client.trackTrace({message: "trace message", tagOverrides:operationIdOverride});
    client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:231, resultCode:0, success: true, dependencyTypeName: "ZSQL", tagOverrides:operationIdOverride});
    client.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true, tagOverrides:operationIdOverride});
};

Parameter tagOverrides menetapkan operation_Id ke ID pemanggilan fungsi. Pengaturan ini memungkinkan Anda menghubungkan semua telemetri yang dihasilkan secara otomatis dan kustom untuk pemanggilan fungsi tertentu.

Pemicu dan pengikatan HTTP

Pemicu HTTP dan webhook dan pengikatan output HTTP menggunakan objek permintaan dan respons untuk mewakili olah pesan HTTP.

Meminta objek

Objek context.req (permintaan) memiliki properti berikut:

Properti Deskripsi
isi Objek yang memuat isi permintaan.
headers Objek yang berisi header permintaan.
method Metode HTTP permintaan.
originalUrl URL permintaan.
params Objek yang berisi parameter perutean permintaan.
query Objek yang berisi parameter kueri.
rawBody Isi pesan sebagai string.

Objek respons

Objek context.res (respons) memiliki properti berikut:

Properti Deskripsi
isi Objek yang memuat isi respons.
headers Objek yang berisi header respons.
isRaw Menunjukkan bahwa pemformatan dilewati untuk respons.
status Kode status HTTP respons.
cookies Larik obyek cookie HTTP yang diatur di dalam respons. Objek cookie HTTP memiliki name, value, dan properti cookie lainnya, seperti maxAge atau sameSite.

Mengakses permintaan dan respons

Saat Anda bekerja dengan pemicu HTTP, Anda dapat mengakses permintaan HTTP dan objek respons dengan berbagai cara:

  • Dari properti req dan res pada objek context. Dengan cara ini, Anda dapat menggunakan pola konvensional untuk mengakses data HTTP dari objek konteks, alih-alih harus menggunakan pola context.bindings.name penuh. Contoh berikut menunjukkan cara mengakses objek req dan res pada context:

    // 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!' }; 
    
  • Dari pengikatan input dan output bernama. Dengan cara ini, pemicu dan pengikatan HTTP berfungsi sama seperti pengikatan lainnya. Contoh berikut mengatur objek respons menggunakan pengikatan bernama response:

    {
        "type": "http",
        "direction": "out",
        "name": "response"
    }
    
    context.bindings.response = { status: 201, body: "Insert succeeded." };
    
  • [Hanya respons] Dengan memanggil context.res.send(body?: any). Respons HTTP dibuat dengan input body sebagai isi respons. context.done() secara implisit dipanggil.

  • [Hanya respons] Dengan memunculkan respons. Nama pengikatan khusus $return memungkinkan Anda menetapkan nilai fungsi yang muncul ke pengikatan output. Pengikatan output HTTP berikut mendefinisikan parameter output $return:

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

    Dalam fungsi 2.x+, Anda dapat memunculkan objek respons secara langsung:

    return { status: 201, body: "Insert succeeded." };
    

Permintaan dan respons ditampilkan dalam huruf kecil.

Penskalaan dan konkurensi

Secara default, Azure Functions secara otomatis memantau beban pada aplikasi Anda dan membuat instans host tambahan untuk Node.js sesuai kebutuhan. Fungsi menggunakan ambang batas bawaan (tidak dapat dikonfigurasi pengguna) untuk berbagai jenis pemicu untuk memutuskan kapan harus menambahkan instans, seperti usia pesan dan ukuran antrean untuk QueueTrigger. Untuk informasi selengkapnya, lihat Cara kerja paket Konsumsi dan Premium.

Perilaku penskalaan ini cukup tersedia untuk sejumlah aplikasi Node.js. Untuk aplikasi yang terikat CPU, Anda dapat meningkatkan performa lebih lanjut dengan menggunakan beberapa proses pekerja bahasa.

Secara default, setiap instans host Functions memiliki proses pekerja bahasa tunggal. Anda dapat meningkatkan jumlah proses pekerja per host (hingga 10) menggunakan pengaturan aplikasi FUNCTIONS_WORKER_PROCESS_COUNT. Azure Functions kemudian mencoba mendistribusikan permintaan fungsi simultan secara merata ke seluruh pekerja. Kemungkinan fungsi intensif CPU memblokir fungsi lain agar tidak berjalan sangat kecil.

Aplikasi FUNCTIONS_WORKER_PROCESS_COUNT berlaku untuk setiap host yang dibuat Functions saat menskalakan aplikasi Anda untuk memenuhi permintaan.

Versi node

Tabel berikut ini memperlihatkan versi Node.js yang didukung saat ini untuk setiap versi utama runtime Functions, menurut sistem operasi:

Versi fungsi Versi node (Windows) Versi node (Linux)
4.x (disarankan) ~16
~14
node|16
node|14
3.x ~14
~12
~10
node|14
node|12
node|10
2.x ~12
~10
~8
node|10
node|8
1.x 6.11.2 (dikunci oleh runtime) n/a

Anda dapat melihat versi saat ini yang digunakan runtime dengan mencatat process.version dari fungsi apa pun.

Mengatur versi Node

Untuk aplikasi fungsi Windows, targetkan versi tersebut di Azure dengan mengatur pengaturan aplikasiWEBSITE_NODE_DEFAULT_VERSION ke versi LTS yang didukung, seperti ~14.

Untuk mempelajari lebih lanjut tentang kebijakan dukungan runtime Azure Functions, lihat artikel ini.

Manajemen dependensi

Untuk menggunakan pustaka komunitas dalam kode JavaScript seperti yang ditunjukkan dalam contoh di bawah ini, pastikan semua dependensi telah diinstal pada Aplikasi Fungsi Anda di Azure.

// Import the underscore.js library
const _ = require('underscore');

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

Catatan

Tentukan file package.json di root Aplikasi Fungsi Anda. Mendefinisikan file memungkinkan semua fungsi dalam aplikasi berbagi paket cache yang sama untuk memberikan performa terbaik. Jika konflik versi muncul, atasi dengan menambahkan file package.json di folder fungsi tertentu.

Saat menerapkan Aplikasi Fungsi dari kontrol sumber, file package.json apa pun yang ada di repositori Anda akan memicu npm install di foldernya selama penyebaran. Tetapi ketika menyebarkan melalui Portal atau CLI, Anda harus memasang paket secara manual.

Ada dua cara untuk menginstal paket di Aplikasi Fungsi Anda:

Menerapkan dengan Dependensi

  1. Instal semua paket yang diperlukan secara lokal dengan menjalankan npm install.

  2. Sebarkan kode Anda, dan pastikan menyertakan folder node_modules di penyebaran tersebut.

Menggunakan Kudu (hanya Windows)

  1. Buka https://<function_app_name>.scm.azurewebsites.net.

  2. Pilih Debug Konsol>CMD.

  3. Masuk ke D:\home\site\wwwroot, lalu seret file package.json Anda ke folder wwwroot di bagian atas halaman.
    Anda juga dapat mengunggah file ke aplikasi fungsi dengan cara lain. Untuk informasi selengkapnya, lihat Cara memperbarui file aplikasi fungsi.

  4. Setelah file package.json diunggah, jalankan perintah npm install di konsol eksekusi jarak jauh Kudu.
    Tindakan ini mengunduh paket yang ada di file package.json dan memulai ulang aplikasi fungsi.

Variabel lingkungan

Tambahkan variabel lingkungan Anda sendiri ke aplikasi fungsi, di lingkungan lokal dan cloud Anda, seperti rahasia operasional (string koneksi, kunci, dan titik akhir) atau pengaturan lingkungan (seperti variabel pembuatan profil). Akses pengaturan ini menggunakan process.env di kode fungsi Anda.

Di lingkungan pengembangan lokal

Saat berjalan secara lokal, proyek fungsi Anda menyertakan file local.settings.json, tempat Anda menyimpan variabel lingkungan di dalam objek Values.

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "",
    "FUNCTIONS_WORKER_RUNTIME": "node",
    "translatorTextEndPoint": "https://api.cognitive.microsofttranslator.com/",
    "translatorTextKey": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
    "languageWorkers__node__arguments": "--prof"
  }
}

Di lingkungan cloud Azure

Saat berjalan di Azure, aplikasi fungsi memungkinkan Anda mengatur dan menggunakan Pengaturan aplikasi, seperti string koneksi layanan, dan mengekspos pengaturan ini sebagai variabel lingkungan selama eksekusi.

Ada beberapa cara yang dapat Anda tambahkan, perbarui, dan hapus pengaturan aplikasi fungsi:

Perubahan pada pengaturan aplikasi fungsi mengharuskan aplikasi fungsi Anda dimulai ulang.

Mengakses variabel lingkungan dalam kode

Akses pengaturan aplikasi sebagai variabel lingkungan menggunakan process.env, seperti yang ditunjukkan di sini pada panggilan kedua dan ketiga ke context.log() tempat kita mencatat variabel lingkungan AzureWebJobsStorage dan WEBSITE_SITE_NAME:

module.exports = async function (context, myTimer) {
    context.log("AzureWebJobsStorage: " + process.env["AzureWebJobsStorage"]);
    context.log("WEBSITE_SITE_NAME: " + process.env["WEBSITE_SITE_NAME"]);
};

Modul ECMAScript (pratinjau)

Catatan

Karena modul ECMAScript saat ini merupakan fitur pratinjau di Node.js 14 dan 16 Azure Functions.

Modul ECMAScript (modul ES) adalah sistem modul standar resmi baru untuk Node.js. Sejauh ini, sampel kode dalam artikel ini menggunakan sintaks CommonJS. Saat menjalankan Azure Functions di Node.js 14 atau lebih tinggi, Anda dapat memilih untuk menulis fungsi menggunakan sintaks modul ES.

Untuk menggunakan modul ES di suatu fungsi, ubah nama filenya untuk menggunakan ekstensi .mjs. Contoh file index.mjs berikut adalah fungsi yang dipicu HTTP yang menggunakan sintaks modul ES untuk mengimpor pustaka uuid dan mengembalikan nilai.

import { v4 as uuidv4 } from 'uuid';

export default async function (context, req) {
    context.res.body = uuidv4();
};

Mengonfigurasi titik entri fungsi

Properti function.jsonscriptFile dan entryPoint dapat digunakan untuk mengonfigurasi lokasi dan nama fungsi yang diekspor. Properti ini bisa menjadi penting ketika JavaScript Anda diterjemahkan ke bahasa pemrograman yang lain.

Menggunakan scriptFile

Fungsi JavaScript dijalankan secara default dari index.js–file yang berbagi direktori induk yang sama dengan direktori yang sesuai function.json.

scriptFile dapat digunakan untuk mendapatkan struktur folder yang terlihat seperti contoh berikut:

FunctionApp
 | - host.json
 | - myNodeFunction
 | | - function.json
 | - lib
 | | - sayHello.js
 | - node_modules
 | | - ... packages ...
 | - package.json

function.json untuk myNodeFunction harus menyertakan properti scriptFile yang mengarah ke file dengan fungsi yang diekspor untuk dijalankan.

{
  "scriptFile": "../lib/sayHello.js",
  "bindings": [
    ...
  ]
}

Menggunakan entryPoint

Di scriptFile (atau index.js), fungsi harus diekspor menggunakan module.exports untuk ditemukan dan dijalankan. Secara default, fungsi yang dijalankan ketika dipicu adalah satu-satunya ekspor dari file itu, ekspor bernama run, atau ekspor bernama index.

Ini dapat dikonfigurasi menggunakan entryPoint di function.json, seperti pada contoh berikut:

{
  "entryPoint": "logFoo",
  "bindings": [
    ...
  ]
}

Dalam Functions v2.x atau lebih tinggi, yang mendukung parameter this dalam fungsi pengguna, kode fungsi tersebut nantinya dapat menjadi seperti dalam contoh berikut:

class MyObj {
    constructor() {
        this.foo = 1;
    };

    async logFoo(context) { 
        context.log("Foo is " + this.foo); 
    }
}

const myObj = new MyObj();
module.exports = myObj;

Dalam contoh ini, penting untuk dicatat bahwa meskipun suatu objek sedang diekspor, tidak ada jaminan bahwa status akan sama antar eksekusi.

Penelusuran kesalahan lokal

Ketika dimulai dengan parameter --inspect, proses Node.js mendengarkan klien debugging pada port yang ditentukan. Di Azure Functions 2.x atau lebih tinggi, Anda dapat menentukan argumen untuk diteruskan ke Node.js yang menjalankan kode dengan menambahkan variabel lingkungan atau Pengaturan Aplikasi languageWorkers:node:arguments = <args>.

Untuk men-debug secara lokal, tambahkan "languageWorkers:node:arguments": "--inspect=5858" di bawah Values file local.settings.json dan lampirkan debugger ke port 5858.

Saat men-debug menggunakan VS Code, parameter --inspect ditambahkan secara otomatis menggunakan nilai port di file proyek launch.json.

Di versi 1.x, pengaturan languageWorkers:node:arguments tidak akan berfungsi. Port debug dapat dipilih dengan parameter --nodeDebugPort pada Azure Functions Core Tools.

Catatan

Anda hanya dapat mengonfigurasi languageWorkers:node:arguments saat menjalankan aplikasi fungsi secara lokal.

Pengujian

Pengujian fungsi meliputi:

  • HTTP menyeluruh: Untuk menguji fungsi dari titik akhir HTTP-nya, Anda dapat menggunakan alat apa pun yang dapat membuat permintaan HTTP seperti cURL, Postman, atau metode pengambilan JavaScript.

  • Pengujian integrasi: Pengujian integrasi mencakup lapisan aplikasi fungsi. Pengujian ini artinya Anda perlu mengontrol parameter ke dalam fungsi termasuk permintaan dan konteksnya. Konteksnya unik untuk setiap jenis pemicu dan Anda perlu mengetahui pengikatan masuk dan keluar untuk jenis pemicu tersebut.

    Pelajari selengkapnya tentang pengujian integrasi dan peniruan lapisan konteks dengan repositori GitHub eksperimental, https://github.com/anthonychu/azure-functions-test-utils.

  • Pengujian unit: Pengujian unit dilakukan dalam aplikasi fungsi. Anda dapat menggunakan alat apa pun yang dapat menguji JavaScript, seperti Jest atau Mocha.

TypeScript

Saat Anda menargetkan runtime Functions versi 2.x atau lebih tinggi, dengan Azure Functions untuk Visual Studio Code dan Azure Functions Core Tools, Anda dapat membuat aplikasi fungsi menggunakan templat yang mendukung proyek aplikasi fungsi TypeScript. Templat menghasilkan file proyek package.json dan tsconfig.json yang membuatnya lebih mudah untuk menerjemahkan pemrograman, menjalankan, dan menerbitkan fungsi JavaScript dari kode TypeScript dengan alat-alat ini.

File .funcignore yang dihasilkan digunakan untuk menunjukkan file mana yang tidak disertakan ketika proyek diterbitkan ke Azure.

File TypeScript (.ts) diterjemahkan ke dalam file JavaScript (.js) di direktori output dist. Templat TypeScript menggunakan parameter scriptFile di function.json untuk menunjukkan lokasi file .js yang sesuai di folder dist. Lokasi output diatur oleh templat dengan menggunakan parameter outDir di file tsconfig.json. Jika Anda mengubah pengaturan ini atau nama folder, runtime tidak dapat menemukan kode yang akan dijalankan.

Cara Anda mengembangkan dan menerapkan proyek TypeScript secara lokal tergantung pada alat pengembangan Anda.

Visual Studio Code

Ekstensi Azure Functions for Visual Studio Code memungkinkan Anda mengembangkan fungsi menggunakan TypeScript. Core Tools adalah persyaratan ekstensi Azure Functions.

Untuk membuat aplikasi fungsi TypeScript di Visual Studio Code, pilih TypeScript sebagai bahasa Anda saat Anda membuat aplikasi fungsi.

Saat Anda menekan F5 untuk menjalankan aplikasi secara lokal, penerjemahan program dilakukan sebelum host (func.exe) diinisialisasi.

Saat Anda menyebarkan aplikasi fungsi ke Azure menggunakan tombol Sebarkan ke aplikasi fungsi... , ekstensi Azure Functions terlebih dahulu menghasilkan build file JavaScript siap produksi dari file sumber TypeScript.

Azure Functions Core Tools

Ada beberapa perbedaan antara proyek TypeScript dan proyek JavaScript saat menggunakan Core Tools.

Membuat proyek

Untuk membuat proyek aplikasi fungsi TypeScript menggunakan Core Tools, tentukan opsi bahasa TypeScript saat membuat aplikasi fungsi. Anda dapat melakukannya dengan salah satu cara berikut:

  • Jalankan perintah func init, pilih node sebagai tumpukan bahasa Anda, lalu pilih typescript.

  • Jalankan perintah func init --worker-runtime typescript.

Jalankan lokal

Untuk menjalankan kode aplikasi fungsi Anda secara lokal dengan Core Tools, gunakan perintah berikut, alih-alih func host start:

npm install
npm start

Perintah npm start setara dengan perintah berikut:

  • npm run build
  • func extensions install
  • tsc
  • func start

Menerbitkan ke Azure

Sebelum Anda menggunakan perintah func azure functionapp publish untuk menyebarkan ke Azure, buatlah build file JavaScript siap produksi dari file sumber TypeScript.

Perintah berikut mempersiapkan dan menerbitkan proyek TypeScript Anda menggunakan Core Tools:

npm run build:production 
func azure functionapp publish <APP_NAME>

Dalam contoh ini, ganti <APP_NAME> dengan nama aplikasi fungsi Anda.

Pertimbangan untuk fungsi JavaScript

Saat Anda bekerja dengan fungsi JavaScript, perhatikan pertimbangan di bagian berikut.

Memilih paket App Service vCPU tunggal

Saat Anda membuat aplikasi fungsi yang menggunakan paket App Service, kami sarankan Anda memilih paket vCPU tunggal daripada paket dengan banyak vCPU. Saat ini, Functions menjalankan fungsi JavaScript dengan lebih efisien pada mesin virtual dengan vCPU tunggal, dan menggunakan mesin virtual yang lebih besar tidak menghasilkan peningkatan performa yang diharapkan. Jika perlu, Anda dapat memperluas skala secara manual dengan menambahkan lebih banyak instans VM dengan vCPU tunggal, atau Anda dapat mengaktifkan autoscale. Untuk informasi selengkapnya, lihat Skalakan jumlah instans secara manual atau otomatis.

Cold Start

Saat mengembangkan Azure Functions dalam model hosting tanpa server, cold start pasti terjadi. Cold start adalah ketika aplikasi fungsi Anda dimulai untuk kali pertama setelah periode tidak aktif, aplikasi akan membutuhkan waktu lebih lama untuk memulai. Khususnya, untuk fungsi JavaScript dengan pohon dependensi yang besar, cold start bisa menjadi hal yang signifikan. Untuk mempercepat proses cold start, jalankan fungsi Anda sebagai file paket jika memungkinkan. Banyak metode penyebaran menggunakan run default dari model paket. Tetapi, jika Anda mengalami cold start yang besar dan tidak menjalankan cara ini, perubahan ini dapat memberikan peningkatan yang signifikan.

Batas Koneksi

Saat Anda menggunakan klien khusus layanan di aplikasi Azure Functions, jangan membuat klien baru pada setiap pemanggilan fungsi. Sebagai gantinya, buat klien statis tunggal di lingkup global. Untuk informasi selengkapnya, lihat mengelola koneksi di Azure Functions.

Gunakan async dan await

Saat menulis Azure Functions di JavaScript, tulis kode menggunakan kata kunci async dan await. Menulis kode menggunakan async dan await alih-alih panggilan balik atau .then dan .catch dengan Promises membantu menghindari dua masalah umum:

  • Melemparkan pengecualian tak tertangkap yang menabrak proses Node.js, yang berpotensi memengaruhi eksekusi fungsi lain.
  • Perilaku tak terduga, seperti log yang hilang dari context.log, disebabkan oleh panggilan asinkron yang tidak diantisipasi dengan benar.

Dalam contoh di bawah ini, metode asinkron fs.readFile dipanggil dengan fungsi panggilan balik kesalahan-pertama sebagai parameter kedua. Kode ini menyebabkan kedua masalah yang disebutkan di atas. Pengecualian yang tidak ditangkap secara eksplisit dalam lingkup yang benar akan merusak seluruh proses (masalah #1). Memanggil context.done() 1.x di luar cakupan fungsi panggilan balik menandakan bahwa pemanggilan fungsi bisa berakhir sebelum file terbaca (masalah #2). Di contoh ini, memanggil context.done() 1.x terlalu dini menyebabkan entri log menghilang, dimulai dengan Data from file:.

// NOT RECOMMENDED PATTERN
const fs = require('fs');

module.exports = function (context) {
    fs.readFile('./hello.txt', (err, data) => {
        if (err) {
            context.log.error('ERROR', err);
            // BUG #1: This will result in an uncaught exception that crashes the entire process
            throw err;
        }
        context.log(`Data from file: ${data}`);
        // context.done() should be called here
    });
    // BUG #2: Data is not guaranteed to be read before the Azure Function's invocation ends
    context.done();
}

Menggunakan kata kunci async dan await membantu menghindari kedua kesalahan ini. Gunakan fungsi utilitas Node.js util.promisify untuk mengubah fungsi gaya panggilan balik kesalahan-pertama menjadi fungsi yang dapat ditunggu.

Dalam contoh di bawah ini, setiap pengecualian yang tidak tertangani yang dilemparkan selama eksekusi fungsi hanya menggagalkan pemanggilan individu yang menimbulkan pengecualian. Kata kunci await bermakna bahwa langkah-langkah yang mengikuti readFileAsync hanya akan mengeksekusi setelah readFile selesai. Dengan async dan await, Anda juga tidak perlu melakukan panggilan balik context.done().

// Recommended pattern
const fs = require('fs');
const util = require('util');
const readFileAsync = util.promisify(fs.readFile);

module.exports = async function (context) {
    let data;
    try {
        data = await readFileAsync('./hello.txt');
    } catch (err) {
        context.log.error('ERROR', err);
        // This rethrown exception will be handled by the Functions Runtime and will only fail the individual invocation
        throw err;
    }
    context.log(`Data from file: ${data}`);
}

Langkah berikutnya

Untuk informasi selengkapnya, lihat sumber berikut ini: