Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Esta referência aborda como desenvolver Funções do Azure usando JavaScript e TypeScript com o @azure/functions pacote npm. Para uma visão geral dos conceitos do Funções do Azure partilhados em todas as linguagens, consulte a referência para desenvolvedores do Funções do Azure.
| Resource | Link |
|---|---|
| Crie a sua primeira função JavaScript | Visual Studio Code/CLI |
| Crie a sua primeira função TypeScript | Visual Studio Code/CLI |
| Cenários e exemplos | JavaScript/TypeScript |
| Referência da API |
@azure/functions API |
Nota
Este artigo mostra o conteúdo para uma versão específica do modelo de programação com base no seletor no topo da página. A versão que escolheres deve corresponder à versão do teu @azure/functions pacote npm. Não podes misturar funções v3 e v4 na mesma aplicação. Se não tiveres o pacote no teu package.json, a predefinição é a v3.
Modelo de programação
Funções do Azure for Node.js suporta duas versões de modelos de programação. Novos projetos devem usar a v4.
| Feature | v4 (recomendado) | v3 |
|---|---|---|
| Status | disponibilidade geral | GA (manutenção) |
@azure/functions Pacote |
4.x | 3.x |
| Registo de funções | Centrado no código (app.http(), app.timer()) |
Baseado em ficheiros (function.json) |
| Estrutura do ficheiro | Flexível | Fixo (uma pasta por função) |
| Versão do runtime do Functions | 4.25+ | 4.x |
| Node.js versões | 24.x, 22.x | 24.x, 22.x |
No modelo de programação Node.js v4, registas funções importando o objeto app de @azure/functions e chamando métodos específicos do trigger. As funções são definidas diretamente no teu código com uma estrutura de ficheiros flexível. Cada função tem um único gatilho que inicia a sua execução e pode também ter bindings, que são ligações declarativas a outros serviços para ler dados de entrada ou escrever dados de saída. Para mais informações, consulte Acionadores e associações.
No modelo v4, pode:
- Registar funções usando métodos específicos de trigger como
app.http(),app.timer(), eapp.storageQueue(). - Acede à entrada do trigger como primeiro argumento para o teu handler (por exemplo,
HttpRequest). - Devolva a saída principal diretamente da função handler.
- Utilize
context.extraInputs.get()para ler de associações de entrada adicionais, como o Armazenamento de Blobs. - Use
context.extraOutputs.set()para escrever em associações de saída adicionais, como filas. - Cada função tem exatamente um gatilho, mas pode ter múltiplos inputs e saídas extra.
- Pode armazenar dados em cache em variáveis globais para reutilizar entre invocações, mas não conte com a persistência desse estado. O tempo de execução pode reciclar o seu trabalhador a qualquer momento.
No modelo de programação Node.js v3, define-se cada função usando um function.json ficheiro de configuração e código JavaScript ou TypeScript correspondente. Organizas funções em pastas separadas com estruturas de ficheiros específicas. Cada função tem um único gatilho que inicia a sua execução e pode também ter bindings, que são ligações declarativas a outros serviços para ler dados de entrada ou escrever dados de saída. Para mais informações, consulte Gatilhos e associações.
No modelo v3, pode:
- Defina gatilhos e ligações num
function.jsonficheiro. Usedirection: "in"para entradas edirection: "out"para saídas. - Acede à entrada do acionador como o segundo argumento para o teu processador, ou lê-a a partir de
context.bindings. - Defina as saídas atribuindo valores a
context.bindings(por exemplo,context.bindings.outputQueue). Para HTTP, usecontext.res. - Os projetos TypeScript requerem uma
scriptFilepropriedade emfunction.jsonque aponte para o ficheiro JavaScript compilado. - Cada função tem exatamente um trigger, mas pode ter múltiplas ligações de entrada e saída.
- Pode armazenar dados em cache em variáveis globais para reutilizar entre invocações, mas não conte com a persistência desse estado. O tempo de execução pode reciclar o seu trabalhador a qualquer momento.
Examples
Aqui está uma função simples que responde a um pedido HTTP:
const { app } = require('@azure/functions');
app.http('httpTrigger', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
const name = request.query.get('name') || 'World';
context.log('HTTP trigger function processed a request.');
return { body: `Hello, ${name}!` };
}
});
O seguinte exemplo não-HTTP usa um gatilho temporizador:
const { app } = require('@azure/functions');
app.timer('cleanupTimer', {
schedule: '0 */5 * * * *',
handler: async (myTimer, context) => {
context.log('Timer trigger function ran at', new Date().toISOString());
}
});
O exemplo seguinte mostra um gatilho HTTP com uma associação de saída para uma fila:
const { app, output } = require('@azure/functions');
const queueOutput = output.storageQueue({
queueName: 'work-items',
connection: 'AzureWebJobsStorage'
});
app.http('submitWorkItem', {
methods: ['POST'],
extraOutputs: [queueOutput],
handler: async (request, context) => {
const body = await request.json();
context.extraOutputs.set(queueOutput, JSON.stringify(body));
return { status: 202, jsonBody: { accepted: true } };
}
});
Aqui está uma função simples que responde a um pedido HTTP:
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, req) {
const name = (req.query.name || (req.body && req.body.name)) || 'World';
context.log('HTTP trigger function processed a request.');
context.res = {
body: `Hello, ${name}!`
};
};
O seguinte exemplo não-HTTP usa um gatilho temporizador:
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */5 * * * *"
}
]
}
module.exports = async function (context, myTimer) {
context.log('Timer trigger function ran at', new Date().toISOString());
};
O exemplo seguinte apresenta um gatilho HTTP com uma associação de saída a uma fila:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["post"]
},
{
"type": "queue",
"direction": "out",
"name": "workItems",
"queueName": "work-items",
"connection": "AzureWebJobsStorage"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, req) {
const payload = req.body || {};
context.bindings.workItems = JSON.stringify(payload);
context.res = {
status: 202,
body: { accepted: true }
};
};
Criar a sua aplicação de funções
Esta secção cobre os componentes essenciais para criar e estruturar a sua aplicação de funções Node, incluindo a @azure/functions biblioteca, a estrutura do projeto e a gestão de pacotes.
A @azure/functions biblioteca
A @azure/functions biblioteca TypeScript/JavaScript fornece os tipos e funções principais que utiliza para interagir com o runtime do Funções do Azure. Para ver todos os tipos e métodos disponíveis, visite a @azure/functions API.
O seu código de função pode usar @azure/functions para:
- Registar funções e definir acionadores (modelo v4).
- Aceder a dados de entrada do acionador com tipagem forte (por exemplo,
HttpRequest,Timer). - Crie valores de saída tipados (como
HttpResponseInit). - Interagir com o contexto fornecido em tempo de execução e com dados de associação.
Se estiver a usar @azure/functions na sua aplicação, inclua-a nas dependências dos seus projetos:
{
"dependencies": {
"@azure/functions": "^4.0.0"
}
}
Nota
A @azure/functions biblioteca define a superfície de programação para Node.js Funções do Azure, mas não é um SDK de uso geral. Use-o especificamente para criar e executar funções dentro do runtime do Funções do Azure.
Configuração do TypeScript
Para obter a melhor experiência de desenvolvimento em TypeScript, certifique-se de que o seu tsconfig.json inclui a configuração adequada:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "dist",
"rootDir": ".",
"sourceMap": true,
"strict": false,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Estrutura de pastas
Um projeto JavaScript requer a estrutura de pastas mostrada no seguinte exemplo:
<project_root>/
| - .vscode/
| - node_modules/
| - myFirstFunction/
| | - index.js
| | - function.json
| - mySecondFunction/
| | - index.js
| | - function.json
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
A pasta principal do projeto, <project_root>, pode conter os seguintes arquivos:
- .vscode/: (Opcional) Contém a configuração Visual Studio Code armazenada. Para saber mais, consulte Visual Studio Code definições.
- myFirstFunction/function.json: Contém a configuração para o gatilho, entradas e saídas da função. O nome do diretório determina o nome da sua função.
- myFirstFunction/index.js: Armazena seu código de função. Para alterar esse caminho de arquivo padrão, consulte usando scriptFile.
- .funcignore: (Opcional) Declara ficheiros que não deveriam ser publicados em Azure. Normalmente, este ficheiro contém .vscode/ para ignorar as definições do seu editor, testar/ ignorar casos de teste e local.settings.json para impedir que as definições locais da aplicação sejam publicadas.
- host.json: Contém opções de configuração que afetam todas as funções em uma instância de aplicativo de função. Este ficheiro é publicado no Azure. Nem todas as opções são suportadas quando executadas localmente. Para saber mais, consulte host.json.
- local.settings.json: Usado para armazenar configurações de aplicativos e cadeias de conexão quando executado localmente. Este ficheiro não é publicado no Azure. Para saber mais, consulte local.settings.file.
- package.json: Contém opções de configuração como uma lista de dependências de pacotes, o ponto de entrada principal e scripts.
Um projeto JavaScript segue a estrutura de pastas recomendada no seguinte exemplo:
<project_root>/
| - .vscode/
| - node_modules/
| - src/
| | - functions/
| | | - myFirstFunction.js
| | | - mySecondFunction.js
| - test/
| | - functions/
| | | - myFirstFunction.test.js
| | | - mySecondFunction.test.js
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
A pasta principal do projeto, <project_root>, pode conter os seguintes arquivos:
- .vscode/: (Opcional) Contém a configuração Visual Studio Code armazenada. Para saber mais, consulte Visual Studio Code definições.
- src/functions/: O local padrão para todas as funções e seus gatilhos e ligações relacionados.
- test/: (Opcional) Contém os casos de teste do seu aplicativo de função.
- .funcignore: (Opcional) Declara ficheiros que não deveriam ser publicados em Azure. Normalmente, este ficheiro contém .vscode/ para ignorar as definições do seu editor, testar/ ignorar casos de teste e local.settings.json para impedir que as definições locais da aplicação sejam publicadas.
- host.json: Contém opções de configuração que afetam todas as funções em uma instância de aplicativo de função. Este ficheiro é publicado no Azure. Nem todas as opções são suportadas quando executadas localmente. Para saber mais, consulte host.json.
- local.settings.json: Usado para armazenar configurações de aplicativos e cadeias de conexão quando executado localmente. Este ficheiro não é publicado no Azure. Para saber mais, consulte local.settings.file.
- package.json: Contém opções de configuração como uma lista de dependências de pacotes, o ponto de entrada principal e scripts.
Gestão de pacotes
Uma gestão eficaz de pacotes é crucial para Node.js Funções do Azure projetos. Esta secção aborda a gestão de dependências, a configuração de pacotes e as melhores práticas para manter as dependências da sua aplicação de funções.
Gerir dependências
Todos os Node.js Funções do Azure projetos usam o npm para gestão de pacotes. O teu package.json ficheiro define a configuração do projeto, as dependências e os scripts necessários para construir e executar as tuas funções.
Estrutura essencial do package.json:
{
"name": "my-functions-app",
"version": "1.0.0",
"description": "Azure Functions Node.js app",
"main": "src/index.js",
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"prestart": "npm run build",
"start": "func start",
"test": "jest"
},
"dependencies": {
"@azure/functions": "^4.0.0"
},
"devDependencies": {
"@azure/functions-core-tools": "^4.0.4670",
"@types/node": "^18.0.0",
"typescript": "^4.0.0",
"jest": "^29.0.0"
}
}
Dependências de tempo de execução vs. dependências de desenvolvimento
Separe as suas dependências adequadamente:
Dependências em tempo de execução (dependencies):
-
@azure/functions: A biblioteca central do Funções do Azure - Bibliotecas de lógica de negócio (lodash, axios e pacotes semelhantes)
- Controladores de bases de dados (mongodb, mssql e pacotes semelhantes)
- SDK do Azure pacotes (@azure/storage-blob, @azure/cosmos, e pacotes semelhantes)
Dependências de desenvolvimento (devDependencies):
- Compilador TypeScript e definições de tipos
- Frameworks de teste (Jest, Mocha)
- Ferramentas de construção e linters
- Funções do Azure Core Tools (para desenvolvimento local)
Pacotes específicos do TypeScript
Para projetos TypeScript, inclua estas dependências essenciais de desenvolvimento:
{
"devDependencies": {
"@types/node": "^18.0.0",
"typescript": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0"
}
}
Segurança e atualizações
Atualize regularmente as suas dependências para resolver vulnerabilidades de segurança:
# Check for outdated packages
npm outdated
# Update packages
npm update
# Audit for security issues
npm audit
npm audit fix
Execução e depuração
Esta secção abrange o desenvolvimento local, técnicas de depuração e estratégias de teste para Node.js Funções do Azure.
Estrutura de desenvolvimento local
Pré-requisitos:
- Node.js versão 18.x ou 20.x
- Funções do Azure Core Tools v4.x
- CLI do Azure (opcional)
Passos de configuração:
Dependências de instalação:
npm installCompilar projetos TypeScript:
npm run buildIniciar o tempo de execução local:
npm start # or directly: func start
Configuração do ambiente
Configure o seu ambiente de desenvolvimento local utilizando local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "node",
"NODE_ENV": "development",
"CUSTOM_ENV_VARIABLE": "local-value"
},
"Host": {
"LocalHttpPort": 7071,
"CORS": "*",
"CORSCredentials": false
}
}
Debugging
Depuração do Visual Studio Code:
Criar .vscode/launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Node Functions",
"type": "node",
"request": "attach",
"port": 9229,
"preLaunchTask": "func: host start"
}
]
}
Criar .vscode/tasks.json:
{
"version": "2.0.0",
"tasks": [
{
"type": "func",
"label": "func: host start",
"command": "host start",
"problemMatcher": "$func-node-watch",
"isBackground": true,
"options": {
"cwd": "${workspaceFolder}"
}
}
]
}
Depuração na linha de comandos:
# Start with debugging enabled
func start --p <port>
# For TypeScript, ensure you build first
npm run build
func start --p 9229
Implantação
Esta secção cobre estratégias de implementação, integração CI/CD e melhores práticas de produção para Node.js Funções do Azure.
Métodos de implantação
1. Implementação do Visual Studio Code:
- Instale a extensão Funções do Azure.
- Clique com o botão direito na sua aplicação de funções no painel do Azure.
- Selecione Implementar para Funcionar Aplicação.
2. Funções do Azure Core Tools:
# Deploy to Azure
func azure functionapp publish <FunctionAppName>
# Deploy with custom settings
func azure functionapp publish <FunctionAppName> --build local --publish-local-settings
3. Implementação do CLI do Azure:
# Deploy from local folder
az functionapp deployment source config-zip \
--resource-group <ResourceGroupName> \
--name <FunctionAppName> \
--src <PathToZipFile>
Configuração de produção
Definições de aplicação no Azure:
Configurar variáveis de ambiente para produção:
-
WEBSITE_NODE_DEFAULT_VERSION: Defina como~18ou~20. -
FUNCTIONS_WORKER_RUNTIME: Defina comonode. - Cadeias de ligação e chaves da API como definições seguras da aplicação.
-
NODE_ENV: Defina comoproduction.
Acionadores e enlaces
O Funções do Azure usa triggers para iniciar a execução de funções e bindings para ligar o seu código a outros serviços como armazenamento, filas e bases de dados. No modelo de programação Node.js, declaras as ligações de forma diferente consoante a versão do modelo.
Existem dois tipos principais de encadernações:
- Triggers (entrada que inicia a função)
- Entradas e saídas (fontes ou destinos de dados extra)
Para mais informações sobre os gatilhos e ligações disponíveis, consulte Triggers and Bindings in Funções do Azure.
Exemplo: Gatilho do Temporizador com Entrada de Blob
Esta função é ativada a cada 10 minutos, lê de um Blob usando entradas extra e regista o conteúdo do blob.
const { app, input } = require('@azure/functions');
let CACHED_BLOB_DATA = null;
const blobInput = input.storageBlob({
connection: 'BLOB_CONNECTION_SETTING',
path: 'mycontainer/myblob.txt'
});
app.timer('TimerTriggerWithBlob', {
schedule: '0 */10 * * * *',
extraInputs: [blobInput],
handler: async (myTimer, context) => {
if (CACHED_BLOB_DATA === null) {
// Read blob content and cache it
CACHED_BLOB_DATA = context.extraInputs.get(blobInput);
context.log(`Blob content cached: ${CACHED_BLOB_DATA?.substring(0, 100)}...`);
}
context.log(`Timer function executed at: ${new Date().toISOString()}`);
context.log(`Using cached data of length: ${CACHED_BLOB_DATA?.length || 0}`);
}
});
Esta função é acionada a cada 10 minutos, lê dados de um blob através da configuração dos bindings e regista o conteúdo do blob.
{
"scriptFile": "index.js",
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "0 */10 * * * *"
},
{
"name": "blobInput",
"type": "blob",
"direction": "in",
"path": "mycontainer/myblob.txt",
"connection": "AzureWebJobsStorage"
}
]
}
let CACHED_BLOB_DATA = null;
module.exports = async function (context, myTimer) {
if (CACHED_BLOB_DATA === null) {
// Read blob content and cache it
CACHED_BLOB_DATA = context.bindings.blobInput;
context.log(`Blob content cached: ${CACHED_BLOB_DATA?.substring(0, 100)}...`);
}
context.log(`Timer function executed at: ${new Date().toISOString()}`);
context.log(`Using cached data of length: ${CACHED_BLOB_DATA?.length || 0}`);
};
Exemplo: Acionador HTTP com saída para fila
Esta função é ativada num pedido HTTP, escreve uma mensagem numa fila de armazenamento e devolve uma resposta HTTP.
const { app, output } = require('@azure/functions');
const queueOutput = output.storageQueue({
connection: 'AzureWebJobsStorage',
queueName: 'myqueue'
});
app.http('httpTriggerWithQueue', {
methods: ['GET', 'POST'],
extraOutputs: [queueOutput],
handler: async (request, context) => {
const name = request.query.get('name') || 'World';
const message = {
id: context.invocationId,
name: name,
timestamp: new Date().toISOString()
};
// Write to queue output
context.extraOutputs.set(queueOutput, JSON.stringify(message));
context.log(`Message sent to queue: ${JSON.stringify(message)}`);
return {
body: `Hello, ${name}! Message queued successfully.`
};
}
});
Esta função é ativada num pedido HTTP, escreve uma mensagem numa fila de armazenamento e devolve uma resposta HTTP.
{
"scriptFile": "index.js",
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "$return"
},
{
"type": "queue",
"direction": "out",
"name": "outputQueue",
"queueName": "myqueue",
"connection": "AzureWebJobsStorage"
}
]
}
module.exports = async function (context, req) {
const name = (req.query.name || (req.body && req.body.name)) || 'World';
const message = {
id: context.invocationId,
name: name,
timestamp: new Date().toISOString()
};
// Write to queue output
context.bindings.outputQueue = JSON.stringify(message);
context.log(`Message sent to queue: ${JSON.stringify(message)}`);
return {
status: 200,
body: `Hello, ${name}! Message queued successfully.`
};
};
Os objetos app, trigger, input e output exportados pelo módulo @azure/functions fornecem métodos específicos de tipo para a maioria dos tipos. Para todos os tipos que não são suportados, um generic método é fornecido para permitir que você especifique manualmente a configuração. O generic método também pode ser usado se você quiser alterar as configurações padrão fornecidas por um método específico do tipo.
O exemplo seguinte é uma função simples acionada por HTTP que utiliza métodos genéricos em substituição a métodos específicos de tipo.
const { app, output, trigger } = require("@azure/functions");
app.generic("helloWorld1", {
trigger: trigger.generic({
type: "httpTrigger",
methods: ["GET", "POST"],
}),
return: output.generic({
type: "http",
}),
handler: async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
return { body: `Hello, world!` };
},
});
::: fim de zona
Contexto de invocação
Cada invocação da sua função recebe um objeto de invocação context . Use este objeto para ler entradas, definir saídas, escrever em logs e aceder a vários metadados. No modelo v3, passas sempre o objeto de contexto como primeiro argumento ao teu handler.
O context objeto inclui as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
invocationId |
A ID da invocação da função atual. |
executionContext |
Consulte o contexto de execução. |
bindings |
Consulte as ligações. |
bindingData |
Metadados sobre a entrada do gatilho para esta invocação, excluindo o valor em si. Por exemplo, um gatilho de hub de eventos tem uma enqueuedTimeUtc propriedade. |
traceContext |
O contexto para o rastreamento distribuído. Para obter mais informações, veja Trace Context. |
bindingDefinitions |
A configuração de suas entradas e saídas, conforme definido em function.json. |
req |
Consulte Solicitação HTTP. |
res |
Consulte a resposta HTTP. |
context.executionContext
O context.executionContext objeto tem as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
invocationId |
A ID da invocação da função atual. |
functionName |
O nome da função que estás a invocar. O nome da pasta que contém o function.json arquivo determina o nome da função. |
functionDirectory |
A pasta que contém o function.json arquivo. |
retryContext |
Consulte o contexto de repetição. |
context.executionContext.retryContext
O context.executionContext.retryContext objeto tem as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
retryCount |
Um número que representa a tentativa atual de novo envio. |
maxRetryCount |
Número máximo de vezes que uma execução é repetida. Um valor de -1 significa repetir tentativas indefinidamente. |
exception |
Exceção que causou a nova tentativa. |
context.bindings
Use o context.bindings objeto para ler entradas ou definir saídas. O exemplo seguinte é um gatilho de fila de armazenamento que utiliza context.bindings para copiar um blob de entrada do armazenamento para um blob de saída do armazenamento. O conteúdo da mensagem de fila substitui {queueTrigger} para ser o nome do ficheiro a ser copiado, com a ajuda de uma expressão de associação.
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"connection": "storage_APPSETTING",
"queueName": "helloworldqueue"
},
{
"name": "myInput",
"type": "blob",
"direction": "in",
"connection": "storage_APPSETTING",
"path": "helloworld/{queueTrigger}"
},
{
"name": "myOutput",
"type": "blob",
"direction": "out",
"connection": "storage_APPSETTING",
"path": "helloworld/{queueTrigger}-copy"
}
module.exports = async function (context, myQueueItem) {
const blobValue = context.bindings.myInput;
context.bindings.myOutput = blobValue;
};
contexto.concluído
O context.done método foi preterido. Antes do Funções do Azure suportar funções assíncronas, sinalizava que a sua função estava concluída chamando context.done():
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
Remova a chamada para context.done(). Marca a tua função como async para que devolva uma promessa (mesmo que não faças await de nada). Assim que sua função termina (em outras palavras, a promessa retornada é resolvida), o modelo v3 sabe que sua função está concluída.
module.exports = async function (context, request) {
context.log("you don't need context.done or an awaited call");
};
Cada invocação da sua função recebe um objeto de invocação context . Este objeto contém informações sobre a sua invocação e métodos de registo. No modelo v4, normalmente passa-se o context objeto como segundo argumento ao seu handler.
A InvocationContext classe inclui as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
invocationId |
A ID da invocação da função atual. |
functionName |
O nome da função. |
extraInputs |
É utilizado para obter os valores das entradas adicionais. Para obter mais informações, consulte entradas e saídas extras. |
extraOutputs |
Usado para definir os valores de saídas extras. Para obter mais informações, consulte entradas e saídas extras. |
retryContext |
Consulte o contexto de repetição. |
traceContext |
O contexto para o rastreamento distribuído. Para obter mais informações, veja Trace Context. |
triggerMetadata |
Metadados sobre a entrada de gatilho para essa invocação, não incluindo o valor em si. Por exemplo, um gatilho de hub de eventos tem uma enqueuedTimeUtc propriedade. |
options |
As opções usadas ao registar a função, após serem validadas e de os valores predefinidos serem explicitamente especificados. |
Contexto de tentativa de repetição
O retryContext objeto tem as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
retryCount |
Um número que representa a tentativa atual de novo envio. |
maxRetryCount |
Número máximo de vezes que uma execução é repetida. Um valor de -1 significa repetir tentativas indefinidamente. |
exception |
Exceção que causou a nova tentativa. |
Para obter mais informações, veja retry-policies.
Registo
No Funções do Azure, usa context.log() para escrever logs. O Funções do Azure integra-se com o Aplicação Azure Insights para capturar melhor os registos da sua aplicação de funções. Application Insights, parte do Azure Monitor, fornece funcionalidades para recolha, representação visual e análise tanto dos registos de aplicação como dos outputs de trace. Para saber mais, consulte monitorização das Funções do Azure.
Nota
Se usares o método alternativo de Node.js console.log , os registos ao nível da aplicação são acompanhados, mas não estão associados a nenhuma função específica. Use context para registos em vez de console para que todos os registos estejam associados a uma função específica.
O exemplo a seguir grava um log no nível "information" padrão, incluindo a ID de invocação:
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
Níveis de log
Além do método padrão context.log , utilize os seguintes métodos para escrever registos em níveis específicos:
| Método | Descrição |
|---|---|
context.log.error() |
Grava um evento de nível de erro nos logs. |
context.log.warn() |
Grava um evento de nível de aviso nos logs. |
context.log.info() |
Grava um evento de nível de informação nos logs. |
context.log.verbose() |
Grava um evento de nível de rastreamento nos logs. |
| Método | Descrição |
|---|---|
context.trace() |
Grava um evento de nível de rastreamento nos logs. |
context.debug() |
Grava um evento de nível de depuração nos logs. |
context.info() |
Grava um evento de nível de informação nos logs. |
context.warn() |
Grava um evento de nível de aviso nos logs. |
context.error() |
Grava um evento de nível de erro nos logs. |
Configurar nível de log
As funções permitem-lhe definir o nível de limiar para rastrear e visualizar registos. Para definir o limite, use a propriedade logging.logLevel no arquivo host.json. Esta propriedade permite-lhe definir um nível padrão para todas as funções ou um limiar para cada função individual. Para obter mais informações, consulte Como configurar o monitoramento para o Funções do Azure.
Monitorizar dados personalizados
Por padrão, o Funções do Azure escreve a saída como registos para o Application Insights. Para mais controlo, utilize o SDK do Node.js Application Insights para enviar logs, métricas e dependências personalizadas para a sua instância do Application Insights.
Nota
Os métodos no Application Insights Node.js SDK podem mudar ao longo do tempo. Podem existir pequenas diferenças de sintaxe em relação aos exemplos aqui apresentados. Para os exemplos mais recentes de utilização de APIs, consulte a documentação do Application Insights Node.js SDK.
Para rastreamento distribuído no modelo de programação Node.js v4, use o @azure/functions-opentelemetry-instrumentation pacote em vez do SDK Application Insights. Este pacote fornece instrumentação automática baseada em OpenTelemetry para Funções do Azure. Para mais informações, consulte o repositório OpenTelemetry Funções do Azure Instrumentation para Node.js GitHub.
const appInsights = require("applicationinsights");
appInsights.setup();
const client = appInsights.defaultClient;
module.exports = async function (context, request) {
// Use this with 'tagOverrides' to correlate custom logs 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,
});
};
O tagOverrides parâmetro define o ID de invocação da operation_Id função. Esta configuração permite-lhe correlacionar todos os registos gerados automaticamente e personalizados para uma dada invocação de função.
Gatilhos HTTP
Os gatilhos HTTP e webhook usam objetos de solicitação e resposta para representar mensagens HTTP.
HTTP e webhook disparam o uso de HttpRequest e HttpResponse objetos para representar mensagens HTTP. As classes representam um subconjunto do padrão fetch, utilizando o undici pacote do Node.js.
Pedido HTTP
Aceda ao pedido de várias formas:
Como segundo argumento para a sua função:
module.exports = async function (context, request) { context.log(`Http function processed request for url "${request.url}"`);
Da
context.reqpropriedade:module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.req.url}"`);
A partir das ligações de entrada nomeadas: Esta opção funciona da mesma forma que qualquer ligação que não seja HTTP. O nome da associação em
function.jsondeve corresponder à chave emcontext.bindings, ou "request1" no exemplo a seguir:{ "name": "request1", "type": "httpTrigger", "direction": "in", "authLevel": "anonymous", "methods": ["get", "post"] }module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.bindings.request1.url}"`);
O HttpRequest objeto tem as seguintes propriedades:
| Propriedade | Tipo | Descrição |
|---|---|---|
method |
string |
Método de solicitação HTTP usado para invocar essa função. |
url |
string |
URL da solicitação. |
headers |
Record<string, string> |
Cabeçalhos de solicitação HTTP. Este objeto diferencia maiúsculas de minúsculas. Use request.getHeader('header-name') em vez disso, que não faz distinção entre maiúsculas e minúsculas. |
query |
Record<string, string> |
Consultar chaves e valores de parâmetros de cadeia de caracteres da URL. |
params |
Record<string, string> |
Chaves e valores de parâmetros de rota. |
user |
HttpRequestUser \| null |
Objeto que representa o usuário conectado, seja por meio da autenticação de funções, autenticação SWA ou nulo quando nenhum usuário estiver conectado. |
body |
Buffer \| string \| any |
Se o tipo de mídia for "application/octet-stream" ou "multipart/*", body é um Buffer. Se o valor for uma cadeia de caracteres passível de análise JSON, body será o objeto analisado. Caso contrário, body é uma cadeia de caracteres. |
rawBody |
string |
O corpo como uma corda. Apesar do nome, essa propriedade não retorna um Buffer. |
bufferBody |
Buffer |
O corpo como um tampão. |
Podes aceder ao pedido como o primeiro argumento ao teu handler para uma função ativada por HTTP.
async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
O HttpRequest objeto tem as seguintes propriedades:
| Propriedade | Tipo | Descrição |
|---|---|---|
method |
string |
Método de solicitação HTTP usado para invocar essa função. |
url |
string |
URL da solicitação. |
headers |
Headers |
Cabeçalhos de solicitação HTTP. |
query |
URLSearchParams |
Consultar chaves e valores de parâmetros de cadeia de caracteres da URL. |
params |
Record<string, string> |
Chaves e valores de parâmetros de rota. |
user |
HttpRequestUser \| null |
Objeto que representa o usuário conectado, seja por meio da autenticação de funções, autenticação SWA ou nulo quando nenhum usuário estiver conectado. |
body |
ReadableStream \| null |
Corpo como um fluxo legível. |
bodyUsed |
boolean |
Um valor booleano que indica se o corpo já foi lido. |
Para aceder ao corpo de um pedido ou resposta, utilize os seguintes métodos:
| Método | Tipo de Retorno |
|---|---|
arrayBuffer() |
Promise<ArrayBuffer> |
blob() |
Promise<Blob> |
formData() |
Promise<FormData> |
json() |
Promise<unknown> |
text() |
Promise<string> |
Nota
Só podes executar as funções corporais uma vez. As chamadas subsequentes devolvem strings vazias ou ArrayBuffers.
Resposta HTTP
Pode definir a resposta de várias formas. Por exemplo, você pode usar:
Defina a
context.respropriedade:module.exports = async function (context, request) { context.res = { body: `Hello, world!` };
Retornar a resposta: Se a função estiver assíncrona e você definir o nome da vinculação como
$returnnofunction.json, poderá retornar a resposta diretamente em vez de defini-la nocontext.{ "type": "http", "direction": "out", "name": "$return" }module.exports = async function (context, request) { return { body: `Hello, world!` };
Defina a ligação de saída nomeada: Esta opção funciona da mesma forma que qualquer ligação que não seja HTTP. O nome da associação em
function.jsondeve corresponder à chave emcontext.bindings, ou "response1" no exemplo a seguir:{ "type": "http", "direction": "out", "name": "response1" }module.exports = async function (context, request) { context.bindings.response1 = { body: `Hello, world!` };
Chamada
context.res.send(): Esta opção está obsoleta. Ele chamacontext.done()implicitamente e não podes usá-lo numa função assíncrona.module.exports = function (context, request) { context.res.send(`Hello, world!`);
Se você criar um novo objeto ao definir a resposta, esse objeto deverá corresponder à HttpResponseSimple interface, que tem as seguintes propriedades:
| Propriedade | Tipo | Descrição |
|---|---|---|
headers |
Record<string, string> (opcional) |
Cabeçalhos de resposta HTTP. |
cookies |
Cookie[] (opcional) |
Cookies de resposta HTTP. |
body |
any (opcional) |
Corpo de resposta HTTP. |
statusCode |
number (opcional) |
Código de status da resposta HTTP. Se não estiver definido, o padrão será 200. |
status |
number (opcional) |
O mesmo que statusCode. Esta propriedade será ignorada se statusCode estiver definida. |
Você também pode modificar o context.res objeto sem substituí-lo. O objeto padrão context.res usa a HttpResponseFull interface, que suporta os seguintes métodos, além das HttpResponseSimple propriedades:
| Método | Descrição |
|---|---|
status() |
Define o estado. |
setHeader() |
Configura um campo de cabeçalho.
NOTA:res.set() e res.header() também são suportados e fazem o mesmo. |
getHeader() |
Recebe um campo de cabeça.
NOTA:res.get() também é suportado e faz o mesmo. |
removeHeader() |
Remove um cabeçalho. |
type() |
Define o cabeçalho "content-type". |
send() |
Este método foi preterido. Ele define o corpo e as chamadas context.done() para indicar que uma função de sincronização foi concluída.
NOTA:res.end() também é suportado e faz a mesma coisa. |
sendStatus() |
Este método foi preterido. Ele define o código de status e as chamadas context.done() para indicar que uma função de sincronização foi concluída. |
json() |
Este método foi preterido. Ele define o "content-type" como "application/json", define o corpo e chama context.done() para indicar que uma função de sincronização foi concluída. |
Pode definir a resposta de várias formas. Por exemplo, você pode usar:
Uma interface simples com tipo
HttpResponseInit: Esta opção é a forma mais concisa de devolver respostas.return { body: `Hello, world!` };
A HttpResponseInit interface tem as seguintes propriedades:
| Propriedade | Tipo | Descrição |
|---|---|---|
body |
BodyInit (opcional) |
Corpo de resposta HTTP como um dos ArrayBuffer, , , AsyncIterable<Uint8Array>, Blob, FormDataIterable<Uint8Array>, NodeJS.ArrayBufferViewURLSearchParams, , ou nullstring. |
jsonBody |
any (opcional) |
Um corpo de resposta HTTP serializável por JSON. Se definido, a propriedade HttpResponseInit.body é ignorada em favor desta propriedade. |
status |
number (opcional) |
Código de status da resposta HTTP. Se não estiver definido, o padrão será 200. |
headers |
HeadersInit (opcional) |
Cabeçalhos de resposta HTTP. |
cookies |
Cookie[] (opcional) |
Cookies de resposta HTTP. |
Como uma classe com tipo
HttpResponse: Esta opção fornece métodos auxiliares para ler e modificar várias partes da resposta, como os cabeçalhos.const response = new HttpResponse({ body: `Hello, world!` }); response.headers.set("content-type", "application/json"); return response;
A HttpResponse classe aceita um opcional HttpResponseInit como um argumento para seu construtor e tem as seguintes propriedades:
| Propriedade | Tipo | Descrição |
|---|---|---|
status |
number |
Código de status da resposta HTTP. |
headers |
Headers |
Cabeçalhos de resposta HTTP. |
cookies |
Cookie[] |
Cookies de resposta HTTP. |
body |
ReadableStream | null |
Corpo como um fluxo legível. |
bodyUsed |
boolean |
Um valor booleano que indica se o corpo já foi lido. |
Fluxos HTTP
Os fluxos HTTP são um recurso que facilita o processamento de dados grandes, o streaming de respostas OpenAI, o fornecimento de conteúdo dinâmico e o suporte a outros cenários HTTP principais. Ele permite que você transmita solicitações e respostas de pontos de extremidade HTTP em seu aplicativo de função Node.js. Use fluxos HTTP em cenários em que seu aplicativo requer troca e interação em tempo real entre cliente e servidor por HTTP. Você também pode usar fluxos HTTP para obter o melhor desempenho e confiabilidade para seus aplicativos ao usar HTTP.
Importante
Os fluxos HTTP não são suportados no modelo v3.
Atualize para o modelo v4 para usar o recurso de streaming HTTP.
Os tipos HttpRequest e HttpResponse existentes no modelo de programação v4 já suportam diversas formas de lidar com o corpo da mensagem, incluindo como fluxo.
Pré-requisitos
- O
@azure/functionspacote npm versão 4.3.0 ou posterior. - Funções do Azure runtime versão 4.28 ou posterior.
- Funções do Azure Core Tools versão 4.0.5530 ou posterior, que contém a versão correta em tempo de execução.
Ativar fluxos
Use estes passos para ativar fluxos HTTP na sua aplicação de funções no Azure e nos seus projetos locais:
Se planeias transmitir grandes quantidades de dados, modifica a definição
FUNCTIONS_REQUEST_BODY_SIZE_LIMITno Azure. O tamanho máximo do corpo permitido por predefinição é104857600, o que limita os seus pedidos a cerca de 100 MB.Para o desenvolvimento local, adicione também
FUNCTIONS_REQUEST_BODY_SIZE_LIMITao arquivo local.settings.json.Adicione o seguinte código à sua aplicação em qualquer ficheiro incluído pelo campo principal.
const { app } = require("@azure/functions"); app.setup({ enableHttpStream: true });
Exemplos de fluxo
O exemplo seguinte mostra uma função ativada por HTTP que recebe dados através de um pedido HTTP POST. A função transmite estes dados para um ficheiro de saída especificado:
const { app } = require('@azure/functions');
const { createWriteStream } = require('fs');
const { Writable } = require('stream');
app.http('httpTriggerStreamRequest', {
methods: ['POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
const writeStream = createWriteStream('<output file path>');
await request.body.pipeTo(Writable.toWeb(writeStream));
return { body: 'Done!' };
},
});
O exemplo seguinte mostra uma função ativada por HTTP que transmite o conteúdo de um ficheiro como resposta a pedidos HTTP GET recebidos:
const { app } = require('@azure/functions');
const { createReadStream } = require('fs');
app.http('httpTriggerStreamResponse', {
methods: ['GET'],
authLevel: 'anonymous',
handler: async (request, context) => {
const body = createReadStream('<input file path>');
return { body };
},
});
Para uma aplicação de exemplo pronta a executar que usa streams, veja este exemplo no GitHub.
Considerações sobre o fluxo
- Utilize
request.bodypara tirar o máximo partido dos fluxos. Continua a ser possível usar métodos comorequest.text(), que devolvem sempre o corpo como uma cadeia de caracteres.
Ganchos
O modelo v3 não suporta ganchos. Atualize para o modelo v4 para usar ganchos.
Use um gancho para executar código em diferentes pontos do ciclo de vida do Funções do Azure. A ordem em que registas os hooks determina a ordem em que são executados. Podes criar ganchos a partir de qualquer ficheiro na tua aplicação. Existem dois âmbitos de hooks: ao nível da aplicação e ao nível da invocação.
Ganchos de invocação
Os ganchos de invocação funcionam uma vez por invocação da tua função. Um preInvocation gancho corre antes da função ser executada, e um postInvocation gancho corre depois da função ser executada. Por defeito, o teu hook é executado para todos os tipos de acionador, mas também o podes filtrar por tipo. O exemplo a seguir mostra como registrar um gancho de invocação e filtrar por tipo de gatilho:
const { app } = require('@azure/functions');
// Pre-invocation hook with trigger filtering
app.hook.preInvocation('httpPreInvocation', async (context) => {
context.hookData.startTime = Date.now();
context.invocationContext.log(`Pre-invocation hook executed for ${context.invocationContext.functionName}`);
// Add custom headers or modify function handler if needed
if (context.functionHandler.name === 'httpTrigger') {
context.invocationContext.log('HTTP function detected, preparing request processing');
}
}, {
filter: ['httpTrigger']
});
// Post-invocation hook
app.hook.postInvocation('httpPostInvocation', async (context) => {
const duration = Date.now() - context.hookData.startTime;
context.invocationContext.log(`Function ${context.invocationContext.functionName} completed in ${duration}ms`);
// Log results or errors
if (context.error) {
context.invocationContext.log.error(`Function failed: ${context.error.message}`);
} else {
context.invocationContext.log(`Function succeeded with result: ${JSON.stringify(context.result)}`);
}
}, {
filter: ['httpTrigger']
});
O primeiro argumento para o manipulador de gancho é um objeto de contexto específico para esse tipo de gancho.
O PreInvocationContext objeto tem as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
inputs |
Os argumentos que transmites à invocação. |
functionHandler |
O manipulador de função para a invocação. As alterações nesse valor afetam a própria função. |
invocationContext |
O objeto de contexto de invocação passou para a função. |
hookData |
O local recomendado para armazenar e partilhar dados entre "hooks" (pontos de ancoragem) no mesmo âmbito. Utilize um nome de propriedade único para que não entre em conflito com os dados de outros hooks. |
O PostInvocationContext objeto tem as seguintes propriedades:
| Propriedade | Descrição |
|---|---|
inputs |
Os argumentos que transmites à invocação. |
result |
O resultado da função. As alterações a este valor afetam o resultado geral da função. |
error |
O erro gerado pela função, ou null/undefined se não houver nenhum erro. As alterações a este valor afetam o resultado geral da função. |
invocationContext |
O objeto de contexto de invocação passou para a função. |
hookData |
O local recomendado para armazenar e partilhar dados entre "hooks" (pontos de ancoragem) no mesmo âmbito. Utilize um nome de propriedade único para que não entre em conflito com os dados de outros hooks. |
Ganchos de aplicativo
O ambiente de execução executa os hooks da aplicação uma vez por cada instância da sua aplicação. Executa appStart ganchos durante o arranque e appTerminate ganchos durante a terminação. Os ganchos de encerramento de aplicativo têm um tempo limitado para serem executados e não são executados em todos os cenários.
O runtime Funções do Azure atualmente não suporta registo de contexto fora de uma invocação. Use o pacote npm do Application Insights para registrar dados durante ganchos no nível do aplicativo.
O exemplo a seguir registra hooks de aplicação:
const { app } = require('@azure/functions');
const appInsights = require('applicationinsights');
// Initialize Application Insights for app-level logging
appInsights.setup().start();
const client = appInsights.defaultClient;
// App start hook
app.hook.appStart('appStartup', async (context) => {
context.hookData.appStartTime = Date.now();
context.hookData.initializationData = {};
// Initialize shared resources, database connections, etc.
client.trackEvent({
name: 'FunctionAppStarted',
properties: {
timestamp: new Date().toISOString(),
nodeVersion: process.version
}
});
// Set up global configurations
process.env.APP_INITIALIZED = 'true';
});
// App terminate hook
app.hook.appTerminate('appShutdown', async (context) => {
const uptime = Date.now() - context.hookData.appStartTime;
// Cleanup resources, close connections, etc.
client.trackEvent({
name: 'FunctionAppTerminated',
properties: {
uptime: uptime,
timestamp: new Date().toISOString()
}
});
// Flush Application Insights data
await new Promise((resolve) => client.flush({ callback: resolve }));
});
O primeiro argumento para o manipulador de gancho é um objeto de contexto específico para esse tipo de gancho.
O AppStartContext objeto tem a seguinte propriedade:
| Propriedade | Descrição |
|---|---|
hookData |
O local recomendado para armazenar e partilhar dados entre "hooks" (pontos de ancoragem) no mesmo âmbito. Utilize um nome de propriedade único para que não entre em conflito com os dados de outros hooks. |
O AppTerminateContext objeto tem a seguinte propriedade:
| Propriedade | Descrição |
|---|---|
hookData |
O local recomendado para armazenar e partilhar dados entre "hooks" (pontos de ancoragem) no mesmo âmbito. Use um nome de propriedade único para que não conflite com os dados de outros ganchos. |
Melhores práticas para ganchos
Ao usar ganchos no seu Funções do Azure, considere estas melhores práticas:
Considerações sobre desempenho
- Mantenha o tempo de execução do hook mínimo para evitar afetar o desempenho da função.
- Use operações assíncronas sempre que possível para evitar bloqueios.
- Considere os custos indiretos dos hooks ao processar solicitações em grande volume.
Tratamento de erros
- Inclua sempre um tratamento adequado de erros nos seus hooks.
- Não deixes que falhas nos ganchos causem falhas funcionais, a menos que seja absolutamente necessário.
- Registe adequadamente os erros dos hooks para depuração.
Partilha de dados
- Uso
hookDatapara partilhar informação entre ganchos pré e pós invocação. - Utilize nomes de propriedades únicos para evitar conflitos com outros hooks.
- Limpar os dados associados aos hooks quando já não forem necessários para evitar fugas de memória.
Filtragem
- Use filtragem por tipo de gatilho para garantir que os hooks só funcionam para funções relevantes.
- Seja específico com os seus filtros para otimizar o desempenho.
Dimensionamento e simultaneidade
Por padrão, o Funções do Azure monitoriza automaticamente a carga na sua aplicação e cria mais instâncias de host para Node.js conforme necessário. O Funções do Azure utiliza limiares incorporados (não configuráveis pelo utilizador) para diferentes tipos de gatilhos para decidir quando adicionar instâncias, como a idade das mensagens e o tamanho da fila para QueueTrigger. Para obter mais informações, consulte Como funcionam os planos Consumo e Premium.
Esse comportamento de dimensionamento é suficiente para muitos aplicativos Node.js. Para aplicativos vinculados à CPU, você pode melhorar ainda mais o desempenho usando vários processos de trabalho de idioma. Você pode aumentar o número de processos de trabalho por host do padrão de 1 até um máximo de 10, usando a configuração de aplicativo FUNCTIONS_WORKER_PROCESS_COUNT. Funções do Azure tenta então distribuir uniformemente as invocações simultâneas de funções entre estes trabalhadores. Esse comportamento torna menos provável que uma função com uso intensivo de CPU bloqueie a execução de outras funções. A definição aplica-se a cada host que o Funções do Azure cria ao escalar a sua aplicação para responder à procura.
Aviso
Use a FUNCTIONS_WORKER_PROCESS_COUNT configuração com cuidado. Vários processos em execução na mesma instância podem levar a um comportamento imprevisível e aumentar os tempos de carregamento da função. Se usares esta configuração, executar a partir de um ficheiro de pacote pode compensar estas desvantagens.
Versão do Node.js
Você pode ver a versão atual que o tempo de execução está a usar ao fazer logging de process.version a partir de qualquer função. Consulte supported versions para obter uma lista de Node.js versões suportadas por cada modelo de programação.
Definindo a versão do Node
A maneira como você atualiza sua versão Node.js depende do sistema operacional no qual seu aplicativo de função é executado.
Quando é executado no Windows, defina a versão do Node.js utilizando a definição da aplicação WEBSITE_NODE_DEFAULT_VERSION. Atualize esta configuração utilizando a CLI do Azure ou através do portal do Azure.
Para obter mais informações sobre Node.js versões, consulte Versões suportadas.
Antes de atualizares a versão Node.js, certifica-te de que a tua aplicação de funções está a correr na versão mais recente do tempo de execução Funções do Azure. Se precisares de atualizar a tua versão de runtime, vê Migrar aplicações da versão Funções do Azure 3.x para a versão 4.x.
- CLI do Azure
- Portal do Azure
Execute o comando CLI do Azure az functionapp config appsettings set para atualizar a versão Node.js da sua aplicação de funções a correr no Windows:
az functionapp config appsettings set --settings WEBSITE_NODE_DEFAULT_VERSION=~22 \
--name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>
Este comando define a WEBSITE_NODE_DEFAULT_VERSION definição da aplicação para a versão ~22LTS suportada.
Depois de fazeres alterações, a tua aplicação de funções reinicia. Para saber mais sobre o suporte para Functions para Node.js, consulte a Política de suporte ao tempo de execução de linguagens.
Variáveis de ambiente
Use variáveis de ambiente para gerir segredos operacionais, como strings de ligação, chaves e endpoints. Também os use para definições ambientais, como perfilar variáveis. Adicione variáveis de ambiente tanto no seu ambiente local como no cloud, e acede a elas através process.env do seu código de função.
O exemplo a seguir registra a WEBSITE_SITE_NAME variável de ambiente:
module.exports = async function (context) {
context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
};
async function timerTrigger1(myTimer, context) {
context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
}
Em ambiente de desenvolvimento local
Quando você executa localmente, seu projeto de funções inclui um local.settings.json arquivo, onde você armazena suas variáveis de Values ambiente no objeto.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"CUSTOM_ENV_VAR_1": "hello",
"CUSTOM_ENV_VAR_2": "world"
}
}
No ambiente cloud do Azure
Quando executas em Azure, a aplicação de funções permite-te definir e usar definições de aplicação, como cadeias de ligação de serviço, e expõe essas definições como variáveis de ambiente durante a execução.
Há várias maneiras de adicionar, atualizar e excluir as configurações do aplicativo de função:
As alterações nas configurações do aplicativo de função exigem que seu aplicativo de função seja reiniciado.
Variáveis do ambiente de trabalho
Node.js tem várias variáveis de ambiente de Funções que lhe são específicas:
languageWorkers__node__arguments
Use esta configuração para especificar argumentos personalizados ao iniciar o seu processo de Node.js. Na maioria das vezes, usas localmente para iniciar o worker em modo de depuração, mas também podes usá-lo no Azure se precisares de argumentos personalizados.
Aviso
Se possível, evite usar languageWorkers__node__arguments no Azure porque pode afetar negativamente os tempos de arranque a frio. Em vez de usar processos de trabalho pré-inicializados, o runtime tem de iniciar um novo processo de trabalho do zero com os argumentos personalizados.
RegistrologLevelWorker
Use esta definição para ajustar o nível padrão do log para registos de trabalhadores específicos de Node.js. Por padrão, apenas os logs de aviso ou erro são mostrados, mas você pode defini-los para information ou debug para ajudar a diagnosticar problemas com o trabalhador Node.js. Para obter mais informações, consulte a configuração de níveis de log.
Módulos ECMAScript (pré-visualização)
Nota
Os módulos ECMAScript são atualmente uma funcionalidade de pré-visualização em Node.js 14 ou superiores em Funções do Azure.
Os módulos ECMAScript (módulos ES) são o novo sistema de módulos padrão oficial para Node.js. Até agora, os exemplos de código neste artigo usam a sintaxe CommonJS. Ao executar Funções do Azure em Node.js 14 ou superior, pode escolher escrever as suas funções usando a sintaxe dos módulos ES.
Para usar módulos ES em uma função, altere seu nome de arquivo para usar uma .mjs extensão. O exemplo de arquivo index.mjs a seguir é uma função acionada por HTTP que usa a sintaxe dos módulos ES para importar a uuid biblioteca e retornar um valor.
import { v4 as uuidv4 } from "uuid";
async function httpTrigger1(context, request) {
context.res.body = uuidv4();
}
export default httpTrigger;
import { v4 as uuidv4 } from "uuid";
async function httpTrigger1(request, context) {
return { body: uuidv4() };
}
app.http("httpTrigger1", {
methods: ["GET", "POST"],
handler: httpTrigger1,
});
Configurar ponto de entrada de função
Utilize as propriedades function.jsonscriptFile e entryPoint para definir a localização e o nome da função exportada. Quando usas TypeScript, precisas da scriptFile propriedade e ela deve apontar para o JavaScript compilado.
Ao utilizar scriptFile
Por defeito, uma função JavaScript corre a partir de index.js. Este ficheiro partilha o mesmo diretório pai que o ficheiro correspondente function.json .
Use scriptFile para organizar a estrutura das suas pastas. O exemplo seguinte mostra uma forma de configurar as suas pastas:
<project_root>/
| - node_modules/
| - myFirstFunction/
| | - function.json
| - lib/
| | - sayHello.js
| - host.json
| - package.json
O ficheiro function.json para myFirstFunction deve incluir a propriedade scriptFile, que aponta para o ficheiro que contém a função exportada a executar.
{
"scriptFile": "../lib/sayHello.js",
"bindings": [
...
]
}
Ao utilizar entryPoint
No modelo v3, deves exportar uma função usando module.exports para que a função possa ser encontrada e executada. Por predefinição, a função que é executada quando é acionada é a única exportação do ficheiro. Também pode ser a exportação com o nome run ou a exportação com o nome index. O exemplo seguinte define o código entryPoint em function.json com um valor personalizado, "logHello":
{
"entryPoint": "logHello",
"bindings": [
...
]
}
async function logHello(context) {
context.log("Hello, world!");
}
module.exports = { logHello };
Recomendações
Esta secção descreve vários padrões impactantes para Node.js aplicações que deve seguir.
Escolha planos de Serviço de Aplicativo de única vCPU
Quando criar uma aplicação de funções que utiliza o plano App Service, selecione um plano de vCPU único em vez de um plano com múltiplas vCPUs. Hoje em dia, o Functions corre Node.js funções de forma mais eficiente em VMs de um único vCPU, e usar VMs maiores não traz as melhorias de desempenho esperadas. Quando necessário, pode escalar adicionando mais instâncias de VM de vCPU único, ou pode ativar a autoescalabilidade. Para obter mais informações, consulte Dimensionar a contagem de instâncias manualmente ou automaticamente.
Executar a partir de um arquivo de pacote
Quando se desenvolvem Funções do Azure no modelo de alojamento serverless, os cold starts são uma realidade. Arranque a frio refere-se à primeira vez que a sua função é iniciada após um período de inatividade, levando mais tempo para arrancar. Para aplicativos Node.js com grandes árvores de dependência em particular, o arranque a frio pode ser significativo. Para acelerar o processo de arranque a frio, execute as suas funções como um ficheiro de pacote sempre que possível. Muitos métodos de implementação usam este modelo por defeito, mas, se estiver a ter arranques a frio muito demorados, verifique se está a executar desta forma.
Utilize async e await
Ao escrever Funções do Azure em Node.js, escreva código utilizando as palavras-chave async e await. Escrever código utilizando async e await em vez de callbacks ou de .then e .catch com promessas ajuda-o a evitar dois problemas comuns:
- Lançar exceções não detetadas que travam o processo de Node.js, potencialmente afetando a execução de outras funções.
- Comportamento inesperado, como logs ausentes do
context.log, devido a chamadas assíncronas que não são aguardadas corretamente.
No exemplo a seguir, o método fs.readFile assíncrono é invocado com uma função de retorno de chamada error-first como seu segundo parâmetro. Este código causa ambos os problemas mencionados anteriormente. Uma exceção que não é explicitamente tratada no escopo correto pode interromper todo o processo (problema #1). Regressar sem garantir que o callback termina significa que a resposta HTTP por vezes tem um corpo vazio (problema #2).
// DO NOT USE THIS CODE
const { app } = require('@azure/functions');
const fs = require('fs');
app.http('httpTriggerBadAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
let fileData;
fs.readFile('./helloWorld.txt', (err, data) => {
if (err) {
context.error(err);
// BUG #1: This will result in an uncaught exception that crashes the entire process
throw err;
}
fileData = data;
});
// BUG #2: fileData is not guaranteed to be set before the invocation ends
return { body: fileData };
},
});
No exemplo a seguir, o método fs.readFile assíncrono é invocado com uma função de retorno de chamada error-first como seu segundo parâmetro. Este código causa ambos os problemas mencionados anteriormente. Uma exceção que não esteja explicitamente detetada no âmbito correto pode fazer todo o processo crashar (problema #1). Chamar o método obsoleto context.done() fora do âmbito do callback pode sinalizar que a função está concluída antes do ficheiro ser lido (problema #2). Neste exemplo, chamar context.done() muito cedo resulta em entradas de log ausentes começando com 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();
};
Utilize as palavras-chave async e await para ajudar a evitar estes dois problemas. A maioria das APIs no ecossistema Node.js agora suporta promessas de alguma forma. Por exemplo, a partir da versão 14, Node.js fornece uma fs/promises API para substituir a fs API de callback.
No exemplo a seguir, quaisquer exceções não tratadas lançadas durante a execução da função só falham a invocação individual que gerou a exceção. A await palavra-chave significa que as etapas seguintes readFile só são executadas depois de concluídas.
// Recommended pattern
const { app } = require('@azure/functions');
const fs = require('fs/promises');
app.http('httpTriggerGoodAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
try {
const fileData = await fs.readFile('./helloWorld.txt');
return { body: fileData };
} catch (err) {
context.error(err);
// This rethrown exception will only fail the individual invocation, instead of crashing the whole process
throw err;
}
},
});
Quando usas async e await, não precisas de chamar o context.done() callback.
// Recommended pattern
const fs = require("fs/promises");
module.exports = async function (context) {
let data;
try {
data = await fs.readFile("./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}`);
};
Resolver problemas
Consulte o Guia de solução de problemas do Node.js.
Próximos passos
Para obter mais informações, consulte os seguintes recursos: