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

您正在查看 Apigee Edge 說明文件。
前往 Apigee X 說明文件
info

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', response1.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 的並行要求過多,後續要求就會失敗,並顯示 500 Internal Server Error 和「Timed out」在 JavaScript 政策逾時之前顯示錯誤訊息。

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

影響

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

最佳做法

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

使用回呼時,執行緒會在 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);

延伸閱讀