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

您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档
信息

通过 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', response1.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 内部服务器错误和“超时”错误消息(在 JavaScript 政策超时之前)。

一般情况下,如果后端处理请求需要很长时间或流量较高,就可能会发生这种情况。

影响

  1. 如果 JavaScript 代码中执行 waitForComplete() 的并发请求数量超过预定义限制,则 API 请求将失败并显示 500 内部服务器错误“超时”错误消息。
  2. 诊断问题的原因可能并不容易,因为即使特定的 JavaScript 政策并未超过时间限制,JavaScript 也会失败并显示“超时”错误。

最佳做法

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

深入阅读