دليل مطوري Azure Functions Node.js
هذا الدليل هو مقدمة لتطوير وظائف Azure باستخدام JavaScript أو TypeScript. تفترض المقالة أنك قرأت بالفعل دليل مطور Azure Functions.
هام
يتغير محتوى هذه المقالة استنادا إلى اختيارك لنموذج البرمجة Node.js في المحدد في أعلى هذه الصفحة. يجب أن يتطابق الإصدار الذي تختاره مع إصدار حزمة npm التي @azure/functions
تستخدمها في تطبيقك. إذا لم يكن لديك تلك الحزمة مدرجة في ، package.json
فإن الافتراضي هو v3. تعرف على المزيد حول الاختلافات بين v3 وv4 في دليل الترحيل.
بصفتك مطور Node.js، قد تكون مهتما أيضا بإحدى المقالات التالية:
الشروع في العمل | المفاهيم | التعلم الموجه |
---|---|---|
الاعتبارات
- لا ينبغي الخلط بين نموذج البرمجة Node.js ووقت تشغيل Azure Functions:
- نموذج البرمجة: يحدد كيفية تأليف التعليمات البرمجية الخاصة بك وهو خاص ب JavaScript وTypeScript.
- وقت التشغيل: يحدد السلوك الأساسي ل Azure Functions ويتم مشاركته عبر جميع اللغات.
- يرتبط إصدار نموذج البرمجة ارتباطا صارما بإصدار حزمة
@azure/functions
npm. يتم إصداره بشكل مستقل عن وقت التشغيل. يستخدم كل من وقت التشغيل ونموذج البرمجة الرقم 4 كإصدار رئيسي أحدث، ولكن هذه صدفة. - لا يمكنك خلط نماذج البرمجة v3 وv4 في نفس تطبيق الوظائف. بمجرد تسجيل وظيفة v4 واحدة في تطبيقك، يتم تجاهل أي وظائف v3 مسجلة في ملفات function.json .
الإصدارات المدعومة
يعرض الجدول التالي كل إصدار من نموذج برمجة Node.js جنبا إلى جنب مع إصداراته المدعومة من وقت تشغيل Azure Functions Node.js.
إصدار نموذج البرمجة | مستوى الدعم | إصدار وقت تشغيل الوظائف | إصدار Node.js | الوصف |
---|---|---|---|---|
4.x | التوفر العام | 4.25+ | 20.x، 18.x | يدعم بنية ملف مرنة ونهج يركز على التعليمات البرمجية للمشغلات والروابط. |
3.x | التوفر العام | 4.x | 20.x، 18.x، 16.x، 14.x | يتطلب بنية ملف معينة مع المشغلات والروابط المعلن عنها في ملف "function.json" |
2.x | غير متوفر | 3.x | 14.x، 12.x، 10.x | تم الوصول إلى انتهاء الدعم في 13 ديسمبر 2022. راجع إصدارات الوظائف لمزيد من المعلومات. |
1.x | غير متوفر | 2.x | 10.x، 8.x | تم الوصول إلى انتهاء الدعم في 13 ديسمبر 2022. راجع إصدارات الوظائف لمزيد من المعلومات. |
بنية المجلد
تبدو بنية المجلد المطلوبة لمشروع JavaScript مثل المثال التالي:
<project_root>/
| - .vscode/
| - node_modules/
| - myFirstFunction/
| | - index.js
| | - function.json
| - mySecondFunction/
| | - index.js
| | - function.json
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
يمكن أن يحتوي مجلد المشروع الرئيسي، <project_root>، على الملفات التالية:
- .vscode/: (اختياري) يحتوي على تكوين Visual Studio Code المخزن. لمعرفة المزيد، راجع إعدادات Visual Studio Code.
- myFirstFunction/function.json: يحتوي على تكوين لمشغل الوظيفة والمدخلات والمخرجات. يحدد اسم الدليل اسم الدالة الخاصة بك.
- myFirstFunction/index.js: يخزن التعليمات البرمجية للدالة. لتغيير مسار الملف الافتراضي هذا، راجع استخدام scriptFile.
- .funcignore: (اختياري) يعلن عن الملفات التي لا ينبغي نشرها إلى Azure. عادة ما يحتوي هذا الملف على .vscode/ لتجاهل إعداد المحرر، والاختبار/ لتجاهل حالات الاختبار، local.settings.json لمنع نشر إعدادات التطبيق المحلي.
- host.json: يحتوي على خيارات التكوين التي تؤثر على جميع الوظائف في مثيل تطبيق الوظائف. لا يتم نشر هذا الملف في Azure. لا يتم دعم جميع الخيارات عند التشغيل محليًا. لمعرفة المزيد، راجع host.json.
- local.settings.json: يستخدم لتخزين إعدادات التطبيق سلسلة الاتصال عند تشغيله محليا. لا يتم نشر هذا الملف في Azure. لمعرفة المزيد، راجع local.settings.file.
- package.json: يحتوي على خيارات التكوين مثل قائمة تبعيات الحزمة ونقطة الإدخال الرئيسية والبرامج النصية.
تبدو بنية المجلد الموصى بها لمشروع JavaScript مثل المثال التالي:
<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
يمكن أن يحتوي مجلد المشروع الرئيسي، <project_root>، على الملفات التالية:
- .vscode/: (اختياري) يحتوي على تكوين Visual Studio Code المخزن. لمعرفة المزيد، راجع إعدادات Visual Studio Code.
- src/functions/: الموقع الافتراضي لجميع الدالات والمشغلات والروابط ذات الصلة.
- اختبار/: (اختياري) يحتوي على حالات الاختبار لتطبيق الوظائف.
- .funcignore: (اختياري) يعلن عن الملفات التي لا ينبغي نشرها إلى Azure. عادة ما يحتوي هذا الملف على .vscode/ لتجاهل إعداد المحرر، والاختبار/ لتجاهل حالات الاختبار، local.settings.json لمنع نشر إعدادات التطبيق المحلي.
- host.json: يحتوي على خيارات التكوين التي تؤثر على جميع الوظائف في مثيل تطبيق الوظائف. لا يتم نشر هذا الملف في Azure. لا يتم دعم جميع الخيارات عند التشغيل محليًا. لمعرفة المزيد، راجع host.json.
- local.settings.json: يستخدم لتخزين إعدادات التطبيق سلسلة الاتصال عند تشغيله محليا. لا يتم نشر هذا الملف في Azure. لمعرفة المزيد، راجع local.settings.file.
- package.json: يحتوي على خيارات التكوين مثل قائمة تبعيات الحزمة ونقطة الإدخال الرئيسية والبرامج النصية.
تسجيل دالة
يسجل نموذج v3 دالة استنادا إلى وجود ملفين. أولا، تحتاج إلى function.json
ملف موجود في مجلد بمستوى واحد لأسفل من جذر تطبيقك. ثانيا، تحتاج إلى ملف JavaScript يقوم بتصدير وظيفتك. بشكل افتراضي، يبحث النموذج عن index.js
ملف في نفس المجلد الخاص بك function.json
. إذا كنت تستخدم TypeScript، يجب استخدام الخاصية scriptFile
في function.json
للإشارة إلى ملف JavaScript المحول برمجيا. لتخصيص موقع الملف أو اسم التصدير للدالة، راجع تكوين نقطة إدخال الدالة.
يجب دائما الإعلان عن الدالة async function
التي تقوم بتصديرها ك في نموذج v3. يمكنك تصدير دالة متزامنة، ولكن بعد ذلك يجب عليك استدعاء context.done()
للإشارة إلى اكتمال الدالة الخاصة بك، والتي تم إهمالها ولا يوصى بها.
يتم تمرير دالتك استدعاء context
كوسيطة أولى وإدخالاتك كوسيطات متبقية.
المثال التالي هو دالة بسيطة تسجل أنه تم تشغيلها وتستجيب مع Hello, world!
:
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"authLevel": "anonymous",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, request) {
context.log('Http function was triggered.');
context.res = { body: 'Hello, world!' };
};
يقوم نموذج البرمجة بتحميل وظائفك استنادا إلى الحقل في main
.package.json
يمكنك تعيين main
الحقل إلى ملف واحد أو ملفات متعددة باستخدام نمط glob. يعرض الجدول التالي أمثلة main
على قيم الحقل:
مثال | الوصف |
---|---|
src/index.js |
تسجيل الوظائف من ملف جذر واحد. |
src/functions/*.js |
تسجيل كل دالة من ملفها الخاص. |
src/{index.js,functions/*.js} |
تركيبة حيث تقوم بتسجيل كل وظيفة من ملفها الخاص، ولكن لا يزال لديك ملف جذر للتعليمات البرمجية العامة على مستوى التطبيق. |
لتسجيل دالة، يجب استيراد app
الكائن من الوحدة النمطية @azure/functions
npm واستدعاء الأسلوب الخاص بنوع المشغل الخاص بك. الوسيطة الأولى عند تسجيل دالة هي اسم الدالة. الوسيطة الثانية هي كائن options
يحدد تكوين المشغل والمعالج وأي مدخلات أو مخرجات أخرى. في بعض الحالات التي لا يكون فيها تكوين المشغل ضروريا، يمكنك تمرير المعالج مباشرة كوسيطة ثانية بدلا من كائن options
.
يمكن تسجيل دالة من أي ملف في مشروعك، طالما يتم تحميل هذا الملف (بشكل مباشر أو غير مباشر) استنادا إلى الحقل الموجود main
في package.json
الملف. يجب تسجيل الدالة في نطاق عمومي لأنه لا يمكنك تسجيل الوظائف بمجرد بدء عمليات التنفيذ.
المثال التالي هو دالة بسيطة تسجل أنه تم تشغيلها وتستجيب مع Hello, world!
:
const { app } = require('@azure/functions');
app.http('helloWorld1', {
methods: ['POST', 'GET'],
handler: async (request, context) => {
context.log('Http function was triggered.');
return { body: 'Hello, world!' };
}
});
المدخلات والمخرجات
دالتك مطلوبة للحصول على إدخال أساسي واحد بالضبط يسمى المشغل. قد يحتوي أيضا على مدخلات و/أو مخرجات ثانوية. يتم تكوين المدخلات والمخرجات في ملفاتك function.json
ويشار إليها أيضا باسم الروابط.
الإدخالات
المدخلات هي روابط مع direction
تعيين إلى in
. الفرق الرئيسي بين المشغل والإدخل الثانوي هو أن type
لمشغل ينتهي في Trigger
، على سبيل المثال النوع blobTrigger
مقابل النوع blob
. تستخدم معظم الدالات مشغلا فقط، ولا يتم دعم العديد من أنواع الإدخال الثانوية.
يمكن الوصول إلى المدخلات بعدة طرق:
[مستحسن] كوسيطات تم تمريرها إلى الدالة: استخدم الوسيطات بالترتيب نفسه الذي تم تعريفها به في
function.json
.name
لا تحتاج الخاصية المعرفة فيfunction.json
إلى مطابقة اسم الوسيطة الخاصة بك، على الرغم من أنه يوصى بها من أجل المؤسسة.module.exports = async function (context, myTrigger, myInput, myOtherInput) { ... };
كخصائص
context.bindings
: استخدم المفتاح المطابق للخاصيةname
المحددة في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); };
المخرجات
المخرجات هي روابط مع direction
تعيين إلى out
ويمكن تعيينها بعدة طرق:
[مستحسن للإخراج الفردي] إرجاع القيمة مباشرة: إذا كنت تستخدم دالة غير متزامنة، يمكنك إرجاع القيمة مباشرة. يجب تغيير
name
خاصية ربط الإخراج إلى$return
فيfunction.json
مثل في المثال التالي:{ "name": "$return", "type": "http", "direction": "out" }
module.exports = async function (context, request) { return { body: "Hello, world!" }; }
[مستحسن لمخرجات متعددة] إرجاع كائن يحتوي على كافة المخرجات: إذا كنت تستخدم دالة غير متزامنة، يمكنك إرجاع كائن بخاصية مطابقة لاسم كل ربط في .
function.json
يستخدم المثال التالي روابط الإخراج المسماة "httpResponse" و"queueOutput":{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; return { httpResponse: { body: message }, queueOutput: message }; };
تعيين القيم على
context.bindings
: إذا كنت لا تستخدم دالة غير متزامنة أو كنت لا تريد استخدام الخيارات السابقة، يمكنك تعيين القيم مباشرة علىcontext.bindings
، حيث يتطابق المفتاح مع اسم الربط. يستخدم المثال التالي روابط الإخراج المسماة "httpResponse" و"queueOutput":{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; context.bindings.httpResponse = { body: message }; context.bindings.queueOutput = message; };
نوع بيانات الربط
يمكنك استخدام الخاصية على dataType
ربط إدخال لتغيير نوع الإدخال الخاص بك، ومع ذلك فإنه يحتوي على بعض القيود:
- في Node.js، يتم دعم و
binary
فقطstring
(stream
غير مدعوم) - بالنسبة لإدخالات HTTP، يتم تجاهل الخاصية
dataType
. بدلا من ذلك، استخدم خصائص علىrequest
الكائن للحصول على النص الأساسي بالتنسيق المطلوب. لمزيد من المعلومات، راجع طلب HTTP.
في المثال التالي لمشغل قائمة انتظار التخزين، النوع myQueueItem
الافتراضي هو string
، ولكن إذا قمت بتعيين dataType
إلى binary
، يتغير النوع إلى Node.js Buffer
.
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "helloworldqueue",
"connection": "storage_APPSETTING",
"dataType": "binary"
}
const { Buffer } = require('node:buffer');
module.exports = async function (context, myQueueItem) {
if (typeof myQueueItem === 'string') {
context.log('myQueueItem is a string');
} else if (Buffer.isBuffer(myQueueItem)) {
context.log('myQueueItem is a buffer');
}
};
دالتك مطلوبة للحصول على إدخال أساسي واحد بالضبط يسمى المشغل. قد يحتوي أيضا على مدخلات ثانوية، وإخراج أساسي يسمى إخراج الإرجاع، و/أو المخرجات الثانوية. يشار أيضا إلى المدخلات والمخرجات على أنها روابط خارج سياق نموذج البرمجة Node.js. قبل الإصدار 4 من النموذج، تم تكوين هذه الروابط في function.json
الملفات.
إدخال المشغل
المشغل هو الإدخال أو الإخراج المطلوب الوحيد. بالنسبة لمعظم أنواع المشغلات، يمكنك تسجيل دالة باستخدام أسلوب على الكائن المسمى app
بعد نوع المشغل. يمكنك تحديد التكوين الخاص بالمشغل مباشرة على الوسيطة options
. على سبيل المثال، يسمح لك مشغل HTTP بتحديد مسار. أثناء التنفيذ، يتم تمرير القيمة المقابلة لهذا المشغل كوسيطة أولى إلى المعالج الخاص بك.
const { app } = require('@azure/functions');
app.http('helloWorld1', {
route: 'hello/world',
handler: async (request, context) => {
...
}
});
إرجاع الإخراج
إخراج الإرجاع اختياري، وفي بعض الحالات يتم تكوينه بشكل افتراضي. على سبيل المثال، تم تكوين مشغل HTTP المسجل مع app.http
لإرجاع إخراج استجابة HTTP تلقائيا. بالنسبة لمعظم أنواع الإخراج، يمكنك تحديد تكوين الإرجاع على الوسيطة options
بمساعدة العنصر الذي output
تم تصديره من الوحدة النمطية @azure/functions
. أثناء التنفيذ، يمكنك تعيين هذا الإخراج عن طريق إرجاعه من المعالج الخاص بك.
يستخدم المثال التالي مشغل مؤقت وإخراج قائمة انتظار تخزين:
const { app, output } = require('@azure/functions');
app.timer('timerTrigger1', {
schedule: '0 */5 * * * *',
return: output.storageQueue({
connection: 'storage_APPSETTING',
...
}),
handler: (myTimer, context) => {
return { hello: 'world' }
}
});
مدخلات ومخرجات إضافية
بالإضافة إلى المشغل والإرجاع، يمكنك تحديد مدخلات أو مخرجات إضافية على الوسيطة options
عند تسجيل دالة. input
توفر الكائنات و output
التي تم تصديرها من الوحدة النمطية @azure/functions
أساليب خاصة بالنوع للمساعدة في إنشاء التكوين. أثناء التنفيذ، يمكنك الحصول على القيم أو تعيينها باستخدام context.extraInputs.get
أو context.extraOutputs.set
تمرير كائن التكوين الأصلي كوسيطة أولى.
المثال التالي هو دالة يتم تشغيلها بواسطة قائمة انتظار تخزين، مع إدخال blob تخزين إضافي يتم نسخه إلى إخراج blob تخزين إضافي. يجب أن تكون رسالة قائمة الانتظار اسم ملف وتستبدل {queueTrigger}
باسم الكائن الثنائي كبير الحجم الذي سيتم نسخه، بمساعدة تعبير الربط.
const { app, input, output } = require('@azure/functions');
const blobInput = input.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}',
});
const blobOutput = output.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}-copy',
});
app.storageQueue('copyBlob1', {
queueName: 'copyblobqueue',
connection: 'storage_APPSETTING',
extraInputs: [blobInput],
extraOutputs: [blobOutput],
handler: (queueItem, context) => {
const blobInputValue = context.extraInputs.get(blobInput);
context.extraOutputs.set(blobOutput, blobInputValue);
}
});
المدخلات والمخرجات العامة
app
trigger
توفر الكائنات و input
و و output
التي تم تصديرها بواسطة @azure/functions
الوحدة النمطية أساليب خاصة بالنوع لمعظم الأنواع. بالنسبة لجميع الأنواع غير المدعومة، generic
يتم توفير أسلوب للسماح لك بتحديد التكوين يدويا. generic
يمكن أيضا استخدام الأسلوب إذا كنت تريد تغيير الإعدادات الافتراضية التي يوفرها أسلوب خاص بنوع معين.
المثال التالي هو دالة HTTP بسيطة يتم تشغيلها باستخدام أساليب عامة بدلا من أساليب خاصة بالنوع.
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!` };
}
});
سياق استدعاء
يتم تمرير كل استدعاء للدالة الخاصة بك كائن استدعاء context
، ويستخدم لقراءة المدخلات، وتعيين المخرجات، والكتابة إلى السجلات، وقراءة بيانات التعريف المختلفة. في نموذج v3، كائن السياق هو دائما الوسيطة الأولى التي يتم تمريرها إلى المعالج الخاص بك.
يحتوي context
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
invocationId |
معرف استدعاء الدالة الحالية. |
executionContext |
راجع سياق التنفيذ. |
bindings |
راجع الروابط. |
bindingData |
بيانات التعريف حول إدخال المشغل لهذا الاستدعاء، وليس بما في ذلك القيمة نفسها. على سبيل المثال، يحتوي مشغل مركز الأحداث على enqueuedTimeUtc خاصية . |
traceContext |
سياق التتبع الموزع. لمزيد من المعلومات، انظر Trace Context . |
bindingDefinitions |
تكوين المدخلات والمخرجات الخاصة بك، كما هو محدد في function.json . |
req |
راجع طلب HTTP. |
res |
راجع استجابة HTTP. |
context.executionContext
يحتوي context.executionContext
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
invocationId |
معرف استدعاء الدالة الحالية. |
functionName |
اسم الدالة التي يتم استدعاؤها. يحدد اسم المجلد الذي يحتوي على function.json الملف اسم الدالة. |
functionDirectory |
المجلد الذي يحتوي على function.json الملف. |
retryContext |
راجع سياق إعادة المحاولة. |
context.executionContext.retryContext
يحتوي context.executionContext.retryContext
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
retryCount |
رقم يمثل محاولة إعادة المحاولة الحالية. |
maxRetryCount |
الحد الأقصى لعدد مرات إعادة محاولة تنفيذ. تعني قيمة -1 إعادة المحاولة إلى أجل غير مسمى. |
exception |
الاستثناء الذي تسبب في إعادة المحاولة. |
context.bindings
context.bindings
يتم استخدام الكائن لقراءة المدخلات أو تعيين المخرجات. المثال التالي هو مشغل قائمة انتظار التخزين، والذي يستخدم context.bindings
لنسخ إدخال كائن ثنائي كبير الحجم للتخزين إلى إخراج كائن ثنائي كبير الحجم للتخزين. يستبدل {queueTrigger}
محتوى رسالة قائمة الانتظار باسم الملف الذي سيتم نسخه، بمساعدة تعبير الربط.
{
"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;
};
context.done
الأسلوب context.done
مهمل. قبل دعم الدالات غير المتزامنة، يمكنك الإشارة إلى أن وظيفتك تتم عن طريق استدعاء context.done()
:
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
الآن، يوصى بإزالة الاستدعاء ووضع علامة على context.done()
وظيفتك على أنها غير متزامنة بحيث ترجع وعدا (حتى لو لم تكن await
أي شيء). بمجرد انتهاء الدالة الخاصة بك (بمعنى آخر، يحل الوعد الذي تم إرجاعه)، يعرف نموذج v3 أن وظيفتك قد انتهت.
module.exports = async function (context, request) {
context.log("you don't need context.done or an awaited call")
};
يتم تمرير كل استدعاء للدالة الخاصة بك كائن استدعاء context
، مع معلومات حول استدعاءك والأساليب المستخدمة للتسجيل. في نموذج v4، context
يكون الكائن عادة الوسيطة الثانية التي يتم تمريرها إلى المعالج الخاص بك.
InvocationContext
تحتوي الفئة على الخصائص التالية:
الخاصية | الوصف |
---|---|
invocationId |
معرف استدعاء الدالة الحالية. |
functionName |
اسم الدالة |
extraInputs |
يستخدم للحصول على قيم المدخلات الإضافية. لمزيد من المعلومات، راجع المدخلات والمخرجات الإضافية. |
extraOutputs |
يستخدم لتعيين قيم المخرجات الإضافية. لمزيد من المعلومات، راجع المدخلات والمخرجات الإضافية. |
retryContext |
راجع سياق إعادة المحاولة. |
traceContext |
سياق التتبع الموزع. لمزيد من المعلومات، انظر Trace Context . |
triggerMetadata |
بيانات التعريف حول إدخال المشغل لهذا الاستدعاء، وليس بما في ذلك القيمة نفسها. على سبيل المثال، يحتوي مشغل مركز الأحداث على enqueuedTimeUtc خاصية . |
options |
الخيارات المستخدمة عند تسجيل الدالة، بعد التحقق من صحتها وتحديد الإعدادات الافتراضية بشكل صريح. |
سياق إعادة المحاولة
يحتوي retryContext
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
retryCount |
رقم يمثل محاولة إعادة المحاولة الحالية. |
maxRetryCount |
الحد الأقصى لعدد مرات إعادة محاولة تنفيذ. تعني قيمة -1 إعادة المحاولة إلى أجل غير مسمى. |
exception |
الاستثناء الذي تسبب في إعادة المحاولة. |
لمزيد من المعلومات، انظر retry-policies
.
تسجيل الدخول
في Azure Functions، يوصى باستخدام context.log()
لكتابة السجلات. تتكامل Azure Functions مع Azure Application Insights لالتقاط سجلات تطبيق الوظائف بشكل أفضل. يوفر Application Insights، وهو جزء من Azure Monitor، تسهيلات لجمع كل من سجلات التطبيق ومخرجات التتبع وعرضها وتحليلها. لمعرفة المزيد، يُرجى الرجوع إلى monitoring Azure Functions.
إشعار
إذا كنت تستخدم أسلوب Node.js console.log
البديل، يتم تعقب هذه السجلات على مستوى التطبيق ولن يتم إقرانها بأي وظيفة محددة. يوصى بشدة باستخدامه context
للتسجيل بدلا من console
أن تقترن جميع السجلات بوظيفة معينة.
يكتب المثال التالي سجلا على مستوى "المعلومات" الافتراضي، بما في ذلك معرف استدعاء:
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
مستويات السجل
بالإضافة إلى الأسلوب الافتراضي context.log
، تتوفر الطرق التالية التي تتيح لك كتابة السجلات على مستويات محددة:
الطريقة | الوصف |
---|---|
context.log.error() |
تكتب حدث على مستوى الخطأ على السجلات. |
context.log.warn() |
تكتب حدث مستوى التحذير على السجلات. |
context.log.info() |
كتابة حدث على مستوى المعلومات إلى السجلات. |
context.log.verbose() |
يكتب حدثا على مستوى التتبع إلى السجلات. |
الطريقة | الوصف |
---|---|
context.trace() |
يكتب حدثا على مستوى التتبع إلى السجلات. |
context.debug() |
يكتب حدثا على مستوى تتبع الأخطاء إلى السجلات. |
context.info() |
كتابة حدث على مستوى المعلومات إلى السجلات. |
context.warn() |
تكتب حدث مستوى التحذير على السجلات. |
context.error() |
تكتب حدث على مستوى الخطأ على السجلات. |
تكوين مستوى السجل
تتيح لك Azure Functions تحديد مستوى الحد الذي سيتم استخدامه عند تعقب السجلات وعرضها. لتعيين الحد، استخدم الخاصية logging.logLevel
في host.json
الملف. تتيح لك هذه الخاصية تحديد مستوى افتراضي مطبق على جميع الدالات، أو حد لكل دالة فردية. لمعرفة المزيد، راجع كيفية تكوين مراقبة لـAzure Functions.
تعقب البيانات المخصصة
بشكل افتراضي، تكتب Azure Functions الإخراج كتتتبعات إلى Application Insights. لمزيد من التحكم، يمكنك بدلا من ذلك استخدام Application Insights Node.js SDK لإرسال بيانات مخصصة إلى مثيل Application Insights الخاص بك.
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});
};
المعلمة tagOverrides
تعين operation_Id
لمعرف استدعاء الوظيفة. يمكنك هذا الإعداد من ربط كافة السجلات التي تم إنشاؤها تلقائيا والسجلات المخصصة لاستدعاء دالة معينة.
مشغلات HTTP
تستخدم مشغلات HTTP والإخطار على الويب كائنات الطلب والاستجابة لتمثيل رسائل HTTP.
تستخدم HttpRequest
مشغلات HTTP والإخطار على الويب والكائنات HttpResponse
لتمثيل رسائل HTTP. تمثل الفئات مجموعة فرعية من معيار الإحضار، باستخدام حزمة Node.jsundici
.
طلب HTTP
يمكن الوصول إلى الطلب بعدة طرق:
كوسيطة ثانية لدالتك:
module.exports = async function (context, request) { context.log(`Http function processed request for url "${request.url}"`);
من الخاصية
context.req
:module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.req.url}"`);
من روابط الإدخال المسماة: يعمل هذا الخيار بنفس الطريقة التي يعمل بها أي ربط غير HTTP. يجب أن يتطابق اسم الربط في
function.json
مع المفتاح الموجود علىcontext.bindings
أو "request1" في المثال التالي:{ "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}"`);
يحتوي HttpRequest
الكائن على الخصائص التالية:
الخاصية | نوع | الوصف |
---|---|---|
method |
string |
أسلوب طلب HTTP المستخدم لاستدعاء هذه الدالة. |
url |
string |
طلب عنوان URL. |
headers |
Record<string, string> |
عناوين طلب HTTP. هذا الكائن حساس لحالة الأحرف. يوصى باستخدام request.getHeader('header-name') بدلا من ذلك، وهو غير حساس لحالة الأحرف. |
query |
Record<string, string> |
مفاتيح وقيم معلمات سلسلة الاستعلام من عنوان URL. |
params |
Record<string, string> |
مفاتيح وقيم معلمات المسار. |
user |
HttpRequestUser | null |
كائن يمثل المستخدم الذي قام بتسجيل الدخول، إما من خلال مصادقة الوظائف أو مصادقة SWA أو القيمة الخالية عند عدم تسجيل دخول أي مستخدم من هذا القبيل. |
body |
Buffer | string | any |
إذا كان نوع الوسائط هو "application/octet-stream" أو "multipart/*"، body فهو مخزن مؤقت. إذا كانت القيمة عبارة عن سلسلة قادرة على تحليل JSON، body فهي الكائن الذي تم تحليله. خلاف ذلك، body هو سلسلة. |
rawBody |
string |
النص الأساسي كسلسلة. على الرغم من الاسم، لا ترجع هذه الخاصية مخزنا مؤقتا. |
bufferBody |
Buffer |
النص الأساسي كمخزن مؤقت. |
يمكن الوصول إلى الطلب كوسيطة أولى للمعالج الخاص بك لدالة HTTP التي تم تشغيلها.
async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
يحتوي HttpRequest
الكائن على الخصائص التالية:
الخاصية | نوع | الوصف |
---|---|---|
method |
string |
أسلوب طلب HTTP المستخدم لاستدعاء هذه الدالة. |
url |
string |
طلب عنوان URL. |
headers |
Headers |
عناوين طلب HTTP. |
query |
URLSearchParams |
مفاتيح وقيم معلمات سلسلة الاستعلام من عنوان URL. |
params |
Record<string, string> |
مفاتيح وقيم معلمات المسار. |
user |
HttpRequestUser | null |
كائن يمثل المستخدم الذي قام بتسجيل الدخول، إما من خلال مصادقة الوظائف أو مصادقة SWA أو القيمة الخالية عند عدم تسجيل دخول أي مستخدم من هذا القبيل. |
body |
ReadableStream | null |
النص الأساسي كتدفق قابل للقراءة. |
bodyUsed |
boolean |
قيمة منطقية تشير إلى ما إذا كان النص قد تمت قراءته بالفعل. |
للوصول إلى نص طلب أو استجابة، يمكن استخدام الطرق التالية:
الأسلوب | نوع الإرجاع |
---|---|
arrayBuffer() |
Promise<ArrayBuffer> |
blob() |
Promise<Blob> |
formData() |
Promise<FormData> |
json() |
Promise<unknown> |
text() |
Promise<string> |
إشعار
يمكن تشغيل وظائف الجسم مرة واحدة فقط؛ سيتم حل الاستدعاءات اللاحقة بسلاسل فارغة/ArrayBuffers.
استجابة HTTP
يمكن تعيين الاستجابة بعدة طرق:
تعيين الخاصية
context.res
:module.exports = async function (context, request) { context.res = { body: `Hello, world!` };
إرجاع الاستجابة: إذا كانت الدالة غير متزامنة وقمت بتعيين اسم الربط إلى
$return
فيfunction.json
، يمكنك إرجاع الاستجابة مباشرة بدلا من تعيينها علىcontext
.{ "type": "http", "direction": "out", "name": "$return" }
module.exports = async function (context, request) { return { body: `Hello, world!` };
تعيين ربط الإخراج المسمى: يعمل هذا الخيار بنفس الطريقة التي يعمل بها أي ربط غير HTTP. يجب أن يتطابق اسم الربط في
function.json
مع المفتاح الموجود علىcontext.bindings
أو "response1" في المثال التالي:{ "type": "http", "direction": "out", "name": "response1" }
module.exports = async function (context, request) { context.bindings.response1 = { body: `Hello, world!` };
استدعاء
context.res.send()
: تم إهمال هذا الخيار. يستدعي ضمنياcontext.done()
ولا يمكن استخدامه في دالة غير متزامنة.module.exports = function (context, request) { context.res.send(`Hello, world!`);
إذا قمت بإنشاء كائن جديد عند تعيين الاستجابة، يجب أن يتطابق هذا الكائن مع الواجهة HttpResponseSimple
، التي تحتوي على الخصائص التالية:
الخاصية | نوع | الوصف |
---|---|---|
headers |
Record<string, string> (اختياري) |
عناوين استجابة HTTP. |
cookies |
Cookie[] (اختياري) |
ملفات تعريف ارتباط استجابة HTTP. |
body |
any (اختياري) |
نص استجابة HTTP. |
statusCode |
number (اختياري) |
رمز حالة استجابة HTTP. إذا لم يتم تعيين، يتم تعيين افتراضيا إلى 200 . |
status |
number (اختياري) |
نفس statusCode . يتم تجاهل هذه الخاصية إذا statusCode تم تعيينها. |
يمكنك أيضا تعديل context.res
الكائن دون الكتابة فوقه. يستخدم الكائن الافتراضي context.res
الواجهة HttpResponseFull
التي تدعم الأساليب التالية بالإضافة إلى الخصائص HttpResponseSimple
:
الطريقة | الوصف |
---|---|
status() |
تعيين الحالة. |
setHeader() |
تعيين حقل رأس. ملاحظة: res.set() كما res.header() أنها مدعومة وتفعل الشيء نفسه. |
getHeader() |
الحصول على حقل رأس. ملاحظة: res.get() مدعوم أيضا ويفعل الشيء نفسه. |
removeHeader() |
إزالة رأس. |
type() |
تعيين رأس "نوع المحتوى". |
send() |
تم إهمال هذا الأسلوب. يقوم بتعيين النص الأساسي والمكالمات context.done() للإشارة إلى انتهاء وظيفة المزامنة. ملاحظة: res.end() مدعوم أيضا ويفعل الشيء نفسه. |
sendStatus() |
تم إهمال هذا الأسلوب. يقوم بتعيين رمز الحالة والمكالمات context.done() للإشارة إلى انتهاء وظيفة المزامنة. |
json() |
تم إهمال هذا الأسلوب. يقوم بتعيين "نوع المحتوى" إلى "application/json"، وتعيين النص الأساسي، واستدعاءات context.done() للإشارة إلى انتهاء وظيفة المزامنة. |
يمكن تعيين الاستجابة بعدة طرق:
كواجهة بسيطة مع النوع
HttpResponseInit
: هذا الخيار هو الطريقة الأكثر إيجازا لإعادة الاستجابات.return { body: `Hello, world!` };
تحتوي الواجهة
HttpResponseInit
على الخصائص التالية:الخاصية نوع الوصف body
BodyInit
(اختياري)نص استجابة ArrayBuffer
HTTP كأحد أوAsyncIterable<Uint8Array>
أوBlob
أوFormData
أوIterable<Uint8Array>
أو .NodeJS.ArrayBufferView
string
URLSearchParams
null
jsonBody
any
(اختياري)نص استجابة HTTP قابل للتسلسل JSON. إذا تم تعيينها، يتم تجاهل الخاصية HttpResponseInit.body
لصالح هذه الخاصية.status
number
(اختياري)رمز حالة استجابة HTTP. إذا لم يتم تعيين، يتم تعيين افتراضيا إلى 200
.headers
HeadersInit
(اختياري)عناوين استجابة HTTP. cookies
Cookie[]
(اختياري)ملفات تعريف ارتباط استجابة HTTP. كفئة ذات نوع
HttpResponse
: يوفر هذا الخيار أساليب مساعدة لقراءة وتعديل أجزاء مختلفة من الاستجابة مثل الرؤوس.const response = new HttpResponse({ body: `Hello, world!` }); response.headers.set('content-type', 'application/json'); return response;
HttpResponse
تقبل الفئة اختيارياHttpResponseInit
كوسيطة لمنشئها ولها الخصائص التالية:الخاصية نوع الوصف status
number
رمز حالة استجابة HTTP. headers
Headers
عناوين استجابة HTTP. cookies
Cookie[]
ملفات تعريف ارتباط استجابة HTTP. body
ReadableStream | null
النص الأساسي كتدفق قابل للقراءة. bodyUsed
boolean
قيمة منطقية تشير إلى ما إذا كان قد تمت قراءة النص بالفعل.
تدفقات HTTP
تدفقات HTTP هي ميزة تسهل معالجة البيانات الكبيرة، ودفق استجابات OpenAI، وتقديم محتوى ديناميكي، ودعم سيناريوهات HTTP الأساسية الأخرى. يتيح لك دفق الطلبات والاستجابات من نقاط نهاية HTTP في تطبيق الوظائف Node.js. استخدم تدفقات HTTP في السيناريوهات التي يتطلب فيها تطبيقك التبادل والتفاعل في الوقت الحقيقي بين العميل والخادم عبر HTTP. يمكنك أيضا استخدام تدفقات HTTP للحصول على أفضل أداء وموثوقية لتطبيقاتك عند استخدام HTTP.
هام
تدفقات HTTP غير مدعومة في نموذج v3. قم بالترقية إلى نموذج v4 لاستخدام ميزة تدفق HTTP.
تدعم الأنواع الموجودة HttpRequest
و HttpResponse
في نموذج البرمجة v4 بالفعل طرقا مختلفة للتعامل مع نص الرسالة، بما في ذلك كتدفق.
المتطلبات الأساسية
@azure/functions
إصدار حزمة npm 4.3.0 أو أحدث.- إصدار وقت تشغيل Azure Functions 4.28 أو أحدث.
- Azure Functions Core Tools الإصدار 4.0.5530 أو إصدار أحدث، والذي يحتوي على إصدار وقت التشغيل الصحيح.
تمكين التدفقات
استخدم هذه الخطوات لتمكين تدفقات HTTP في تطبيق الوظائف في Azure وفي مشاريعك المحلية:
إذا كنت تخطط لدفق كميات كبيرة من البيانات، فعدل
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
الإعداد في Azure. الحد الأقصى الافتراضي لحجم النص الأساسي المسموح به هو104857600
، والذي يحد من طلباتك إلى حجم ~100 ميغابايت.للتطوير المحلي، أضف
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
أيضا إلى ملف local.settings.json.أضف التعليمات البرمجية التالية إلى تطبيقك في أي ملف مضمن في حقلك الرئيسي.
const { app } = require('@azure/functions'); app.setup({ enableHttpStream: true });
أمثلة الدفق
يوضح هذا المثال دالة مشغلة بواسطة HTTP تتلقى البيانات عبر طلب HTTP POST، وتبث الدالة هذه البيانات إلى ملف إخراج محدد:
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!' };
},
});
يوضح هذا المثال دالة HTTP المشغلة التي تقوم ببث محتوى الملف كاستجابة لطلبات HTTP GET الواردة:
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 };
},
});
للحصول على نموذج تطبيق جاهز للتشغيل باستخدام التدفقات، راجع هذا المثال على GitHub.
اعتبارات الدفق
- استخدم
request.body
للحصول على أقصى فائدة من استخدام التدفقات. لا يزال بإمكانك الاستمرار في استخدام أساليب مثلrequest.text()
، والتي ترجع دائما النص الأساسي كسلسلة.
Hooks
الخطافات غير مدعومة في نموذج v3. قم بالترقية إلى نموذج v4 لاستخدام الخطافات.
استخدم خطاف لتنفيذ التعليمات البرمجية في نقاط مختلفة في دورة حياة Azure Functions. يتم تنفيذ الخطافات بالترتيب الذي يتم تسجيلها به ويمكن تسجيلها من أي ملف في تطبيقك. هناك حاليا نطاقان من الخطافات، مستوى "التطبيق" ومستوى "استدعاء".
خطافات استدعاء
يتم تنفيذ خطافات استدعاء مرة واحدة لكل استدعاء للدالة الخاصة بك، إما قبل في preInvocation
خطاف أو بعد في postInvocation
خطاف. بشكل افتراضي، يتم تنفيذ خطافك لجميع أنواع المشغلات، ولكن يمكنك أيضا التصفية حسب النوع. يوضح المثال التالي كيفية تسجيل خطاف استدعاء وتصفية حسب نوع المشغل:
const { app } = require('@azure/functions');
app.hook.preInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`preInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
app.hook.postInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`postInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
الوسيطة الأولى لمعالج الخطاف هي كائن سياق خاص بنوع الخطاف هذا.
يحتوي PreInvocationContext
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
inputs |
تم تمرير الوسيطات إلى استدعاء . |
functionHandler |
معالج الدالة للادعاء. تؤثر التغييرات التي تطرأ على هذه القيمة على الدالة نفسها. |
invocationContext |
تم تمرير كائن سياق استدعاء إلى الدالة . |
hookData |
المكان الموصى به لتخزين البيانات ومشاركتها بين الخطافات في نفس النطاق. يجب استخدام اسم خاصية فريد بحيث لا يتعارض مع بيانات الخطافات الأخرى. |
يحتوي PostInvocationContext
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
inputs |
تم تمرير الوسيطات إلى استدعاء . |
result |
نتيجة الدالة. تؤثر التغييرات على هذه القيمة على النتيجة الإجمالية للدالة. |
error |
الخطأ الذي تم طرحه بواسطة الدالة، أو خال/غير معرف إذا لم يكن هناك خطأ. تؤثر التغييرات على هذه القيمة على النتيجة الإجمالية للدالة. |
invocationContext |
تم تمرير كائن سياق استدعاء إلى الدالة . |
hookData |
المكان الموصى به لتخزين البيانات ومشاركتها بين الخطافات في نفس النطاق. يجب استخدام اسم خاصية فريد بحيث لا يتعارض مع بيانات الخطافات الأخرى. |
خطافات التطبيق
يتم تنفيذ خطافات التطبيق مرة واحدة لكل مثيل لتطبيقك، إما أثناء بدء التشغيل في خطاف appStart
أو أثناء الإنهاء في خطاف appTerminate
. خطافات إنهاء التطبيق لها وقت محدود للتنفيذ ولا يتم تنفيذها في جميع السيناريوهات.
لا يدعم وقت تشغيل Azure Functions حاليا تسجيل السياق خارج استدعاء. استخدم حزمة Application Insights npm لتسجيل البيانات أثناء خطافات مستوى التطبيق.
يسجل المثال التالي خطافات التطبيق:
const { app } = require('@azure/functions');
app.hook.appStart((context) => {
// add your logic here
});
app.hook.appTerminate((context) => {
// add your logic here
});
الوسيطة الأولى لمعالج الخطاف هي كائن سياق خاص بنوع الخطاف هذا.
يحتوي AppStartContext
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
hookData |
المكان الموصى به لتخزين البيانات ومشاركتها بين الخطافات في نفس النطاق. يجب استخدام اسم خاصية فريد بحيث لا يتعارض مع بيانات الخطافات الأخرى. |
يحتوي AppTerminateContext
الكائن على الخصائص التالية:
الخاصية | الوصف |
---|---|
hookData |
المكان الموصى به لتخزين البيانات ومشاركتها بين الخطافات في نفس النطاق. يجب استخدام اسم خاصية فريد بحيث لا يتعارض مع بيانات الخطافات الأخرى. |
التحجيم والتزامن
بشكل افتراضي، تراقب Azure Functions تلقائيا الحمل على التطبيق الخاص بك وتنشئ المزيد من مثيلات المضيف Node.js حسب الحاجة. تستخدم Azure Functions حدودا مضمنة (غير قابلة للتكوين من قبل المستخدم) لأنواع المشغلات المختلفة لتحديد وقت إضافة مثيلات، مثل عمر الرسائل وحجم قائمة الانتظار ل QueueTrigger. لمزيد من المعلومات، راجع كيف تعمل Consumption and Premium plans.
سلوك التحجيم هذا كافٍ للعديد من تطبيقات Node.js. بالنسبة إلى التطبيقات المرتبطة بـ CPU، يمكنك تحسين الأداء بشكل أكبر باستخدام عمليات عاملة متعددة اللغة. يمكنك زيادة عدد عمليات العامل لكل مضيف من الافتراضي 1 حتى 10 كحد أقصى باستخدام إعداد تطبيق FUNCTIONS_WORKER_PROCESS_COUNT . يحاول Azure Functions بعد ذلك توزيع استدعاءات الوظيفة المتزامنة عبر هذه العوامل بالتساوي. يقلل هذا السلوك من احتمالية أن تمنع الدالة كثيفة الاستخدام لوحدة المعالجة المركزية الوظائف الأخرى من التشغيل. ينطبق الإعداد على كل مضيف تقوم Azure Functions بإنشائه عند توسيع نطاق التطبيق الخاص بك لتلبية الطلب.
تحذير
FUNCTIONS_WORKER_PROCESS_COUNT
استخدم الإعداد بحذر. يمكن أن تؤدي العمليات المتعددة التي تعمل في نفس المثيل إلى سلوك غير متوقع وزيادة أوقات تحميل الدالة. إذا كنت تستخدم هذا الإعداد، فمن المستحسن للغاية إزاحة هذه الجوانب السلبية عن طريق التشغيل من ملف حزمة.
إصدار Node
يمكنك مشاهدة الإصدار الحالي الذي يستخدمه وقت التشغيل عن طريق تسجيل process.version
من أي وظيفة. راجع supported versions
للحصول على قائمة بالإصدارات Node.js التي يدعمها كل نموذج برمجة.
إعداد إصدار Node
تعتمد الطريقة التي تقوم بها بترقية إصدار Node.js على نظام التشغيل الذي يتم تشغيل تطبيق الوظائف عليه.
عند التشغيل على Windows، يتم تعيين إصدار Node.js بواسطة WEBSITE_NODE_DEFAULT_VERSION
إعداد التطبيق. يمكن تحديث هذا الإعداد إما باستخدام Azure CLI أو في مدخل Microsoft Azure.
لمزيد من المعلومات حول إصدارات Node.js، راجع الإصدارات المدعومة.
قبل ترقية إصدار Node.js، تأكد من تشغيل تطبيق الوظائف على أحدث إصدار من وقت تشغيل Azure Functions. إذا كنت بحاجة إلى ترقية إصدار وقت التشغيل، فشاهد ترحيل التطبيقات من الإصدار 3.x من Azure Functions إلى الإصدار 4.x.
قم بتشغيل الأمر Azure CLI az functionapp config appsettings set
لتحديث الإصدار Node.js لتطبيق الوظائف الذي يعمل على Windows:
az functionapp config appsettings set --settings WEBSITE_NODE_DEFAULT_VERSION=~20 \
--name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>
يؤدي هذا إلى WEBSITE_NODE_DEFAULT_VERSION
تعيين إعداد التطبيق لإصدار LTS المدعوم من ~20
.
بعد إجراء التغييرات، يتم إعادة تشغيل تطبيق الوظائف. لمعرفة المزيد حول دعم الوظائف Node.js، راجع نهج دعم وقت تشغيل اللغة.
متغيرات البيئة
يمكن أن تكون متغيرات البيئة مفيدة للأسرار التشغيلية (سلسلة الاتصال والمفاتيح ونقاط النهاية وما إلى ذلك) أو الإعدادات البيئية مثل متغيرات جمع المعلومات. يمكنك إضافة متغيرات البيئة في كل من البيئات المحلية والسحابية والوصول إليها من خلال process.env
التعليمات البرمجية للوظيفة.
يسجل WEBSITE_SITE_NAME
المثال التالي متغير البيئة:
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"]}`);
}
في بيئة التنمية المحلية
عند التشغيل محليا، يتضمن مشروع الوظائف ملفاlocal.settings.json
، حيث تقوم بتخزين متغيرات البيئة في Values
العنصر .
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"CUSTOM_ENV_VAR_1": "hello",
"CUSTOM_ENV_VAR_2": "world"
}
}
في بيئة سحابة Azure
عند التشغيل في Azure، يتيح لك تطبيق الوظائف تعيين إعدادات التطبيق واستخدامها، مثل سلسلة الاتصال الخدمة، ويعرض هذه الإعدادات كمتغيرات بيئة أثناء التنفيذ.
توجد عدة طرق يمكنك من خلالها إضافة إعدادات تطبيق الوظائف وتحديثها وحذفها:
تتطلب التغييرات في إعدادات تطبيق الوظائف إعادة تشغيل تطبيق الوظائف.
متغيرات بيئة العامل
هناك العديد من متغيرات بيئة الوظائف الخاصة Node.js:
languageWorkers__node__arguments
يسمح لك هذا الإعداد بتحديد وسيطات مخصصة عند بدء عملية Node.js. غالبا ما يتم استخدامه محليا لبدء تشغيل العامل في وضع التصحيح، ولكن يمكن استخدامه أيضا في Azure إذا كنت بحاجة إلى وسيطات مخصصة.
تحذير
إذا كان ذلك ممكنا، تجنب استخدام languageWorkers__node__arguments
في Azure لأنه يمكن أن يكون له تأثير سلبي على أوقات البدء الباردة. بدلا من استخدام عمال تم تجهيزهم مسبقا، يجب أن يبدأ وقت التشغيل عامل جديد من الصفر باستخدام الوسيطات المخصصة.
logging__logLevel__Worker
يضبط هذا الإعداد مستوى السجل الافتراضي لسجلات العامل الخاصة Node.js. بشكل افتراضي، يتم عرض سجلات التحذير أو الخطأ فقط، ولكن يمكنك تعيينها إلى information
أو debug
للمساعدة في تشخيص المشكلات مع العامل Node.js. لمزيد من المعلومات، راجع تكوين مستويات السجل.
وحدات ECMAScript (المعاينة)
إشعار
نظرا لأن وحدات ECMAScript النمطية هي حاليا ميزة معاينة في Node.js 14 أو أعلى في Azure Functions.
وحدات ECMAScript (وحدات ES) هي نظام الوحدات الرسمي الجديد لـ Node.js. حتى الآن، تستخدم نماذج التعليمات البرمجية في هذه المقالة بناء الجملة CommonJS. عند تشغيل Azure Functions في Node.js 14 أو أعلى، يمكنك اختيار كتابة وظائفك باستخدام بناء جملة وحدات ES.
لاستخدام الوحدات ES في وظيفة، غير اسم الملف الخاص بها لاستخدام ملحق .mjs
. المثال التالي لملف index.mjs هو وظيفة HTTP مشغلة تستخدم بناء جملة الوحدات ES لاستيراد المكتبة uuid
وإرجاع قيمة.
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
});
تكوين نقطة إدخال الوظيفة
يمكن استخدام الخصائص function.json
scriptFile
وentryPoint
لتكوين موقع واسم الوظيفة المصدرة. الخاصية scriptFile
مطلوبة عند استخدام TypeScript ويجب أن تشير إلى JavaScript المحول برمجيا.
استخدام scriptFile
بشكل افتراضي، يتم تنفيذ وظيفة JavaScript من index.js
، ملف يشارك نفس الدليل الأصل الذي يشاركه الملف المطابق له function.json
.
يمكن استخدام scriptFile
للحصول على بنية مجلد مماثل للمثال التالي:
<project_root>/
| - node_modules/
| - myFirstFunction/
| | - function.json
| - lib/
| | - sayHello.js
| - host.json
| - package.json
function.json
الخاص بـmyFirstFunction
يجب أن يتضمن خاصية scriptFile
للإشارة إلى الملف الذي يحتوي على الوظيفة المصدرة لتشغيله.
{
"scriptFile": "../lib/sayHello.js",
"bindings": [
...
]
}
استخدام entryPoint
في نموذج v3، يجب تصدير دالة باستخدام module.exports
من أجل العثور عليها وتشغيلها. بشكل افتراضي، الوظيفة التي تنفذ عند تشغيلها هي التصدير الوحيد من ذلك الملف، أو التصدير المسمى run
، أو التصدير المسمى index
. يعين entryPoint
المثال التالي إلى function.json
قيمة مخصصة، "logHello":
{
"entryPoint": "logHello",
"bindings": [
...
]
}
async function logHello(context) {
context.log('Hello, world!');
}
module.exports = { logHello };
التصحيح المحلي
يوصى باستخدام VS Code لتصحيح الأخطاء المحلي، والذي يبدأ عملية Node.js في وضع التصحيح تلقائيا ويرفق بالعملية نيابة عنك. لمزيد من المعلومات، راجع تشغيل الدالة محليا.
إذا كنت تستخدم أداة مختلفة لتصحيح الأخطاء أو تريد بدء عملية Node.js في وضع التصحيح يدويا، أضف "languageWorkers__node__arguments": "--inspect"
ضمن Values
في local.settings.json. تخبر الوسيطة --inspect
Node.js بالاستماع لعميل تصحيح الأخطاء، على المنفذ 9229 بشكل افتراضي. لمزيد من المعلومات، راجع دليل تصحيح الأخطاء Node.js.
التوصيات
يصف هذا القسم العديد من الأنماط المؤثرة لتطبيقات Node.js التي نوصي باتباعها.
اختر خطط خدمة التطبيقات single-vCPU
عند إنشاء تطبيق وظيفة يستخدم خطة خدمة التطبيقات، نوصي بتحديد خطة single-vCPU بدلاً من خطة مع vCPUs متعددة. اليوم، تعمل الدالات Node.js الوظائف بشكل أكثر كفاءة على الأجهزة الظاهرية لوحدة المعالجة المركزية الظاهرية الأحادية، ولا ينتج عن استخدام أجهزة ظاهرية أكبر تحسينات الأداء المتوقعة. عند الضرورة، يمكنك التحجيم يدويًا عن طريق إضافة المزيد من مثيلات single-vCPU VM، أو يمكنك تمكين autoscale. لمزيد من المعلومات، راجع حساب مثيل المقياس يدويًا أو تلقائيًا.
تشغيل من ملف حزمة
عند تطوير Azure Functions في نموذج الاستضافة بلا خادم، تكون البدايات الباردة حقيقة واقعة. تشير البداية الباردة إلى المرة الأولى التي يبدأ فيها تطبيق الوظائف بعد فترة من عدم النشاط، تستغرق وقتا أطول لبدء التشغيل. بالنسبة Node.js التطبيقات ذات أشجار التبعية الكبيرة على وجه الخصوص، يمكن أن يكون البدء البارد مهما. لتسريع عملية التشغيل البارد، شغل وظائفك كملف حزمة عند الإمكان. تستخدم العديد من أساليب التوزيع هذا النموذج بشكل افتراضي، ولكن إذا كنت تواجه عمليات بدء باردة كبيرة، فيجب عليك التحقق للتأكد من أنك تعمل بهذه الطريقة.
استخدام عميل ثابت واحد
عند استخدام عميل خاص بالخدمة في تطبيق Azure Functions، لا تقم بإنشاء عميل جديد مع استدعاء كل وظيفة لأنه يمكنك الوصول إلى حدود الاتصال. بدلاً من ذلك، أنشئ عميلاً ثابتًا، واحدًا في النطاق العمومي. لمزيد من المعلومات، راجع إدارة الاتصالات في Azure Functions.
استخدام async
وawait
عند كتابة Azure Functions في Node.js، يجب كتابة التعليمات البرمجية async
باستخدام الكلمات الأساسية و await
. كتابة التعليمات البرمجية باستخدام async
وawait
بدلاً من عمليات إعادة الاتصال أو .then
و.catch
مع وعود تساعد على تجنب مشكلتين شائعتين:
- طرح الاستثناءات المعلقة التي تعطل عملية Node.js، يحتمل أن يؤثر على تنفيذ وظائف أخرى.
- سلوك غير متوقع، مثل السجلات المفقودة من
context.log
، بسبب استدعاءات غير متزامنة لم يتم انتظارها بشكل صحيح.
في المثال التالي، يتم استدعاء الأسلوب fs.readFile
غير المتزامن مع دالة رد اتصال الخطأ الأول كمعلمة ثانية. تتسبب هذه التعليمة البرمجية في كلتا المشكلتين المذكورتين سابقا. يمكن أن يؤدي الاستثناء الذي لم يتم اكتشافه بشكل صريح في النطاق الصحيح إلى تعطل العملية بأكملها (المشكلة رقم 1). العودة دون التأكد من انتهاء رد الاتصال يعني أن استجابة http سيكون لها في بعض الأحيان نص فارغ (المشكلة #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 };
},
});
في المثال التالي، يتم استدعاء الأسلوب fs.readFile
غير المتزامن مع دالة رد اتصال الخطأ الأول كمعلمة ثانية. تتسبب هذه التعليمة البرمجية في كلتا المشكلتين المذكورتين سابقا. يمكن أن يؤدي الاستثناء الذي لم يتم اكتشافه بشكل صريح في النطاق الصحيح إلى تعطل العملية بأكملها (المشكلة رقم 1). يمكن أن يشير استدعاء الأسلوب المهمل context.done()
خارج نطاق رد الاتصال إلى انتهاء الدالة قبل قراءة الملف (المشكلة رقم 2). في هذا المثال، الاتصال بـcontext.done()
مبكرة جدًا يؤدي إلى إدخالات سجل مفقودة بدءًا من 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();
}
async
استخدم الكلمات الأساسية و await
للمساعدة في تجنب هاتين المشكلتين. تم تحويل معظم واجهات برمجة التطبيقات في النظام البنائي Node.js لدعم الوعود في شكل ما. على سبيل المثال، بدءا من الإصدار 14، يوفر fs/promises
Node.js واجهة برمجة تطبيقات لاستبدال fs
واجهة برمجة تطبيقات رد الاتصال.
في المثال التالي، تفشل أي استثناءات غير معالجة تم طرحها أثناء تنفيذ الدالة فقط في استدعاء الفردية التي أثارت الاستثناء. await
تعني الكلمة الأساسية أن الخطوات التالية readFile
تنفذ فقط بعد اكتمالها.
// 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;
}
},
});
مع async
وawait
، لا تحتاج أيضًا إلى استدعاء إعادة الاتصال context.done()
.
// 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}`);
}
استكشاف الأخطاء وإصلاحها
راجع دليل استكشاف الأخطاء وإصلاحها Node.js.
الخطوات التالية
لمزيد من المعلومات، راجع الموارد التالية: