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

您正在查看 Apigee Edge 說明文件。
查看 Apigee X 說明文件
資訊

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 內部伺服器錯誤」和「逾時」錯誤訊息,即使 JavaScript 政策逾時也一樣。

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

影響程度

  1. 在 JavaScript 程式碼中執行 waitForComplete() 的並行要求數量超過預先定義的限制時,API 要求就會失敗並顯示 500 Internal Server Error 錯誤訊息「逾時」。
  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);

其他資訊