反模式:在 JavaScript 程式碼中使用 waitForComplete()

您正在查看 ApigeeApigee Hybrid 說明文件。
查看 Apigee Edge 說明文件。

JavaScript 政策可讓您新增在 API Proxy 流程內容中執行的自訂程式碼。舉例來說,JavaScript 政策中的自訂程式碼可用於:

  • 取得及設定流程變數
  • 執行自訂邏輯並執行錯誤處理
  • 從要求或回應中擷取資料
  • 動態編輯後端目標網址
  • 在要求或回應中動態新增或移除標頭
  • 剖析 JSON 回應

HTTP 用戶端

JavaScript 政策的一項強大功能是 HTTP 用戶端。HTTP 用戶端 (或 httpClient 物件) 可用於對後端或外部服務發出一或多個呼叫。當您需要呼叫多個外部服務,並在單一 API 中合併回應時,HTTP 用戶端就特別實用。

使用 httpClient 物件向後端發出呼叫的 JavaScript 程式碼範例

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

httpClient 物件會公開兩個方法 getsend (send 在上述範例程式碼中使用),用於發出 HTTP 要求。這兩種方法都是非同步的,並會在實際的 HTTP 要求完成前傳回 exchange 物件。

HTTP 要求可能需要幾秒到幾分鐘的時間。發出 HTTP 要求後,請務必瞭解要求何時完成,以便處理要求的回應。判斷 HTTP 要求何時完成的其中一種最常見方式,就是叫用 exchange 物件的 waitForComplete() 方法。

waitForComplete()

waitForComplete() 方法會暫停執行緒,直到 HTTP 要求完成並傳回回應 (成功/失敗) 為止。接著,系統就能處理來自後端或外部服務的回應。

使用 waitForComplete() 的 JavaScript 程式碼範例

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());
}

反模式

在 JavaScript 程式碼中傳送 HTTP 要求後使用 waitForComplete(),會影響效能。

請考慮下列 JavaScript 程式碼,該程式碼會在傳送 HTTP 要求後呼叫 waitForComplete()

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', response.status);
} else {
   error = exchangeObj.getError();
   context.setVariable('example.error', 'Woops: ' + error);
}

在這個範例中:

  1. JavaScript 程式碼會將 HTTP 要求傳送至後端 API。
  2. 接著,它會呼叫 waitForComplete() 暫停執行,直到要求完成為止。

    waitForComplete() API 會導致執行 JavaScript 程式碼的執行緒遭到封鎖,直到後端完成處理要求並回應為止。

在任何時間點,可同時在訊息處理器上執行 JavaScript 程式碼的執行緒數量 (30%) 有上限。達到此限制後,就不會有任何執行緒可執行 JavaScript 程式碼。因此,如果 JavaScript 程式碼中執行 waitForComplete() API 的並發要求過多,後續要求就會失敗,並在 JavaScript 政策逾時前顯示 500 Internal Server ErrorTimed out 錯誤訊息。

一般來說,如果後端處理要求的時間過長,或是流量過高,就可能發生這種情況。

影響

  1. 如果 JavaScript 程式碼中執行 waitForComplete() 的並行要求數量超過預先定義的限制,API 要求就會失敗,並顯示 500 Internal Server Error 和錯誤訊息 Timed out
  2. 即使特定 JavaScript 政策的時間限制尚未到期,JavaScript 仍會因 Timed out 錯誤而失敗,因此診斷問題原因可能會相當棘手。

最佳做法

請在 HTTP 用戶端中使用回呼,簡化說明代碼並提升效能,並避免在 JavaScript 程式碼中使用 waitForComplete()。這個方法可確保執行 JavaScript 的執行緒不會在 HTTP 要求完成前遭到封鎖。

使用回呼時,執行緒會在 JavaScript 程式碼中傳送 HTTP 要求,並傳回至集區。由於執行緒不再受阻,因此可處理其他要求。當 HTTP 要求完成,且回呼準備就緒可執行時,系統就會建立工作並新增至工作佇列。池中的其中一個執行緒會根據工作優先順序執行回呼。

在 httpClient 中使用回呼的 JavaScript 程式碼範例

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);

延伸閱讀