Antipattern: استخدام قيمة وظيفة الانتظار (()) في رمز JavaScript

أنت الآن بصدد الاطّلاع على مستندات Apigee Edge.
انتقِل إلى مستندات Apigee X.
info

تتيح لك سياسة JavaScript في Apigee Edge إضافة رمز مخصّص يتم تنفيذه ضمن سياق مسار خادم وكيل لواجهة برمجة التطبيقات. على سبيل المثال، يمكن استخدام الرمز المخصّص في سياسة JavaScript لإجراء ما يلي:

  • الحصول على متغيّرات المسار وضبطها
  • تنفيذ منطق مخصّص ومعالجة الأخطاء
  • استخراج البيانات من الطلبات أو الردود
  • تعديل عنوان URL المستهدف في الخلفية بشكل ديناميكي
  • إضافة عناوين أو إزالتها بشكل ديناميكي من طلب أو رد
  • تحليل رد JSON

عميل HTTP

من الميزات القوية في سياسة JavaScript عميل HTTP. يمكن استخدام عميل HTTP (أو عنصر httpClient) لإجراء طلب واحد أو عدة طلبات إلى الخدمات الخارجية أو خدمات الخلفية. يكون عميل HTTP مفيدًا بشكل خاص عندما تكون هناك حاجة إلى إجراء طلبات إلى خدمات خارجية متعددة ودمج الردود في واجهة برمجة تطبيقات واحدة.

مثال على رمز JavaScript يُجري طلبًا إلى الخلفية باستخدام عنصر httpClient

var headers = {'X-SOME-HEADER' : 'some value' };
var myRequest = new Request("http://www.example.com","GET",headers);
var exchange = httpClient.send(myRequest);

يعرض العنصر httpClient طريقتَين هما get وsend (send مستخدَمة في نموذج الرمز النموذجي أعلاه) لإجراء طلبات HTTP. كلتا الطريقتَين غير متزامنتَين وتعرضان كائن exchange قبل اكتمال طلب HTTP الفعلي.

قد تستغرق طلبات HTTP بضع ثوانٍ إلى بضع دقائق. بعد إجراء طلب HTTP، من المهم معرفة متى يكتمل، حتى يمكن معالجة الرد من الطلب. إحدى الطرق الأكثر شيوعًا لتحديد وقت اكتمال طلب HTTP هي استدعاء طريقة waitForComplete() لكائن exchange.

waitForComplete()

توقف طريقة waitForComplete() مؤقتًا سلسلة المحادثات إلى أن يكتمل طلب HTTP ويتم عرض رد (ناجح/غير ناجح). بعد ذلك، يمكن معالجة الرد من خدمة خارجية أو خدمة خلفية.

مثال على رمز JavaScript باستخدام waitForComplete()

var headers = {'X-SOME-HEADER' : 'some value' };
var myRequest = new Request("http://www.example.com","GET",headers);
var exchange = httpClient.send(myRequest);
// Wait for the asynchronous GET request to finish
exchange.waitForComplete();

// Get and Process the response
if (exchange.isSuccess()) {
    var responseObj = exchange.getResponse().content.asJSON;
    return responseObj.access_token;
} else if (exchange.isError()) {
    throw new Error(exchange.getError());
}

نمط غير مستحسن

سيؤدي استخدام waitForComplete() بعد إرسال طلب HTTP في رمز JavaScript إلى التأثير في الأداء.

لنلقِ نظرة على رمز JavaScript التالي الذي يستدعي waitForComplete() بعد إرسال طلب HTTP.

رمز sample.js

// Send the HTTP request
var exchangeObj = httpClient.get("http://example.com");
// Wait until the request is completed
exchangeObj.waitForComplete();
// Check if the request was successful
if (exchangeObj.isSuccess())  {

    response = exchangeObj.getResponse();
    context.setVariable('example.status', response1.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

في هذا المثال:

  1. يرسل رمز JavaScript طلب HTTP إلى واجهة برمجة تطبيقات في الخلفية.
  2. بعد ذلك، يستدعي waitForComplete() لإيقاف التنفيذ مؤقتًا إلى أن يكتمل الطلب.

    تتسبب واجهة برمجة التطبيقات waitForComplete() في حظر سلسلة المحادثات التي تنفّذ رمز JavaScript إلى أن تكمل الخلفية معالجة الطلب وتردّ عليه.

هناك حدّ أقصى لعدد سلاسل المحادثات (30%) التي يمكنها تنفيذ رمز JavaScript في وقت واحد على "معالج الرسائل" في أي وقت. بعد بلوغ هذا الحدّ، لن تكون هناك أي سلاسل محادثات متاحة لتنفيذ رمز JavaScript. لذلك، إذا كان هناك عدد كبير جدًا من الطلبات المتزامنة التي تنفّذ واجهة برمجة التطبيقات waitForComplete() في رمز JavaScript، ستتعذّر الطلبات اللاحقة وستظهر رسالة الخطأ 500 خطأ في الخادم الداخلي ورسالة الخطأ "انتهت المهلة" حتى قبل انتهاء مهلة سياسة JavaScript.

بشكل عام، قد يحدث هذا السيناريو إذا استغرقت الخلفية وقتًا طويلاً لمعالجة الطلبات أو إذا كان هناك عدد كبير من الزيارات.

التأثير

  1. ستتعذّر طلبات واجهة برمجة التطبيقات وستظهر رسالة الخطأ 500 خطأ في الخادم الداخلي و مع رسالة الخطأ "انتهت المهلة" عندما يتجاوز عدد الطلبات المتزامنة التي تنفّذ waitForComplete() في رمز JavaScript الحدّ الأقصى المحدّد مسبقًا.
  2. قد يكون تشخيص سبب المشكلة أمرًا صعبًا لأنّ JavaScript يتعذّر بسبب الخطأ "انتهت المهلة" حتى إذا لم ينقضِ الحدّ الزمني لسياسة JavaScript المحدّدة.

أفضل الممارسات

استخدِم عمليات رد الاتصال في عميل HTTP لتبسيط رمز طلب البيانات وتحسين الأداء وتجنُّب استخدام waitForComplete() في رمز JavaScript. تضمن هذه الطريقة عدم حظر سلسلة المحادثات التي تنفّذ JavaScript إلى أن يكتمل طلب HTTP.

عند استخدام عملية رد الاتصال، تُرسِل سلسلة المحادثات طلبات HTTP في رمز JavaScript وتعود إلى المجموعة. بما أنّ سلسلة المحادثات لم تعُد محظورة، يمكنها معالجة الطلبات الأخرى. بعد اكتمال طلب HTTP وجهوزية عملية معاودة الاتصال للتنفيذ، سيتم إنشاء مهمة وإضافتها إلى قائمة انتظار المهام. ستنفّذ إحدى سلاسل المحادثات من المجموعة عملية رد الاتصال استنادًا إلى أولوية المهمة.

مثال على رمز JavaScript باستخدام عمليات رد الاتصال في httpClient

function onComplete(response,error) {
 // Check if the HTTP request was successful
    if (response) {
      context.setVariable('example.status', response.status);
     } else {
      context.setVariable('example.error', 'Woops: ' + error);
     }
}
// Specify the callback Function as an argument
httpClient.get("http://example.com", onComplete);

محتوى إضافي للقراءة