反模式:在 JavaScript 代码中使用 waitForComplete()

您正在查看 ApigeeApigee Hybrid 文档。
查看 Apigee Edge 文档。

JavaScript 政策允许您添加在 API 代理流上下文中执行的自定义代码。例如,JavaScript 政策中的自定义代码可用于:

  • 获取和设置流变量
  • 执行自定义逻辑并执行故障处理
  • 从请求或响应中提取数据
  • 动态修改后端目标网址
  • 在请求或响应中动态添加或移除标头
  • 解析 JSON 响应

HTTP 客户端

HTTP 客户端是 JavaScript 政策的一项强大功能。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 代码向后端 API 发送 HTTP 请求。
  2. 然后,它调用 waitForComplete() 来暂停执行,直到请求完成。

    waitForComplete() API 阻止执行 JavaScript 代码的线程,直到后端完成请求处理并发回响应。

任何时候在消息处理器中并行执行 JavaScript 代码的线程数上限为 30%。达到该限制后,将会没有任何线程可以执行 JavaScript 代码。因此,如果 JavaScript 代码中执行 waitForComplete() API 的并发请求过多,则后续请求将失败,并返回 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);

更多详情