无法为 JavaScript 中的 Windows.Web.Http.HttpClient 添加超时

Cannot add timeout for Windows.Web.Http.HttpClient in JavaScript

我很难弄清楚如何使用通过 WinRT 提供的 Windows.Web.HttpClient 来设置请求超时。我正在开发的应用程序是一个 JavaScript-type 通用 Windows 应用程序。 "client-side",JavaScript 可以使用在 C# 中编程时通常会使用的各种命名空间。这些命名空间的成员可以通过 window object 访问,如下所示:

const {
  HttpRequestMessage,
  HttpMethod,
  HttpClient,
} = R.pathOr({}, ['Windows', 'Web', 'Http'], window);

我将在下面 post 编写的代码的目标是在应用程序重定向到 URL 之前对 reach-ability 进行简单的 reach-ability 检查,以防有人想知道为什么我有不仅仅是使用 JavaScript 中更标准的方法(例如:XMLHttpRequest)这样做,这是因为 CORS 有时会失败这些请求。由于我在一家大公司工作,要求在所有地方添加适当的 access-control-allow-origin headers 并不容易,除此之外,我们有 side-loading 到设备上的测试人员,运行 代理等...

就是说,虽然我能够找到与手头任务相关的 documentation,但这些示例都是用 C# 编写的,而且我注意到 JavaScript 方面并非所有内容事情与本文档完全一致。

Stack Overflow 用户提出了一个非常相似的问题 here,公认的解决方案是使用 CancellationTokenSource。但是,据我所知,这个问题的 C# 解决方案不适用于 JavaScript 方面,但我确实想出了一个 near-solution 可以使用 setTimeout 取消任务的方法.请注意,为了便于阅读,我在这里编辑了一些代码行。

const isReachable = async (url) => (
  new Promise((resolve) => {
    const message = new HttpRequestMessage();
    message.method = new HttpMethod('HEAD');
    message.requestUri = new Uri(url);
    const client = new HttpClient();
    const task = client.sendRequestAsync(message);
    const timeout = setTimeout(() => task.cancel(), 5000);
    task.done(
      (result) => { // Success
        clearTimeout(timeout);
        resolve(true);
      },
      (result) => { // Failure
        clearTimeout(timeout);
        resolve(false);
      },
    );
  })
);

上面的代码本身似乎运行良好,但后来我注意到传递给回调函数的参数(名为 response 的参数)不是我所期望的。我期望至少类似于 XHR 响应,但我得到的似乎是任务的成功或错误响应。问题是,我确实需要获取状态代码和失败原因,以便为我们的报告记录它(该代码未说明)。

这是我的下一次(部分)尝试,显然,如果我等待响应,那么我实际上确实得到了一个与用于该目的的 XHR 响应足够相似的 object。但是,由于我在这里等待任务,所以我没有将它存储在一个变量中,以便在我超时后可以取消它。

const urlIsReachable = async (url = '') => (
  new Promise(async (resolve) => {
    const request = new HttpRequestMessage();
    request.method = new HttpMethod('HEAD');
    request.requestUri = new Uri(url);
    const client = new HttpClient();
    const response = await client.sendRequestAsync(request);
    const { statusCode: status } = response;
    if (status === 200) {
      resolve(true);
      return;
    }
    resolve(false);
  })
);

总之,我不认为像设置超时阈值这样简单的事情会如此痛苦,但我一直无法找到这样做的方法。

  1. 根据Setting timeout values with WinJS.xhr or HttpClient(HTML):

    When you use XMLHttpRequest, you can set time-out values directly, but you cannot do this when you use Windows.Web.Http.HttpClient

    所以当您使用Windows.Web.Http.HttpClient时无法设置超时。

  2. but then I noticed that the arguments being passed into the callback functions (arg named response) were not what I expected.....The problem is, I do need to get the status code and failure reason so to log it for our reports (that code is not illustrated)

    那是因为您得到的不是 xhr 响应,而是 WinRT Windows.Web.Http.HttpResponseMessage 对象,您可以使用 result.asyncOpType 查看它。如果您想获取错误消息,只需在 onError 回调中使用 result.message:

    task.done(
        (result) => { // Success
            clearTimeout(timeout);
            resolve(true);
        },
        (result) => { // Failure
            let msg=result.message;//message is 'Canceled' if timeout callback's called
            clearTimeout(timeout);
            resolve(false);
        },
    );