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

Posted

技术标签:

【中文标题】无法在 JavaScript 中为 Windows.Web.Http.HttpClient 添加超时【英文标题】:Cannot add timeout for Windows.Web.Http.HttpClient in JavaScript 【发布时间】:2020-01-01 03:22:22 【问题描述】:

我很难弄清楚如何使用通过 WinRT 提供的 Windows.Web.HttpClient 设置请求超时。我正在开发的应用程序是一个 javascript 类型的通用 Windows 应用程序。 “客户端”,JavaScript 可以访问使用在 C# 中编程时通常会使用的各种命名空间。这些命名空间的成员可以像这样从 window 对象访问:

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

我将在下面发布的代码的目标是在应用重定向到 URL 之前对 URL 进行简单的可访问性检查,以防有人想知道为什么我没有使用 JavaScript 中更标准的方法(例如:XMLHttpRequest),这是因为 CORS 有时会失败这些请求。由于我在一家大公司工作,因此要求在任何地方添加适当的 access-control-allow-origin 标头并不容易,除此之外,我们还有测试人员正在侧向加载设备、运行代理等......

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

Stack Overflow 用户提出了一个非常相似的问题here,并且接受的解决方案是使用 CancellationTokenSource。然而,据我所知,这个问题的 C# 解决方案不适用于 JavaScript 方面,但我确实想出了一个接近解决方案,我可以使用 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);
      ,
    );
  )
);

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

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

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):

    使用 XMLHttpRequest 时可以直接设置超时值,但使用 Windows.Web.Http.HttpClient 时不能这样做

    因此在使用 Windows.Web.Http.HttpClient 时无法设置超时。

    但后来我注意到传递给回调函数的参数(名为响应的参数)不是我所期望的.....问题是,我确实需要获取状态代码和失败原因以便记录它用于我们的报告(代码未显示)

    这是因为您得到的不是 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);
        ,
    );
    

【讨论】:

以上是关于无法在 JavaScript 中为 Windows.Web.Http.HttpClient 添加超时的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Cocos2D-X 在 Windows 的 plist 中为 png 充气

在 Safari 中为网站重新加载 javascript 和 css 文件

如何检测标签在Javascript中为空?

在 Javascript 中为数字添加逗号

在 javascript 中为 JWT 生成 JTI 声明

C# - 在 Windows 7 中为所有用户设置目录权限