反模式:在 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 的並行要求過多,後續要求就會失敗,並顯示 500 Internal Server ErrorTimed out 錯誤訊息,即使 JavaScript 政策尚未逾時也一樣。

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

影響

  1. 當 JavaScript 程式碼中執行的並行要求數量超出預先定義的限制時,API 要求會失敗並顯示 500 Internal Server Error ,以及錯誤訊息 Timed outwaitForComplete()
  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);

延伸閱讀