Мне очень трудно понять, как установить время ожидания запроса с помощью Windows.Web.HttpClient, доступного через WinRT. Приложение, над которым я работаю, представляет собой универсальное приложение для Windows типа JavaScript. «на стороне клиента» JavaScript имеет доступ к использованию различных пространств имен, которые обычно используются при программировании на C#. К членам этих пространств имен можно получить доступ из объекта окна следующим образом:
const {
HttpRequestMessage,
HttpMethod,
HttpClient,
} = R.pathOr({}, ['Windows', 'Web', 'Http'], window);
Цель кода, который я опубликую ниже, состоит в том, чтобы выполнить простую проверку доступности URL-адреса до того, как приложение перенаправит его туда, и в случае, если кто-то задается вопросом, почему я просто не сделал этого, используя более стандартные средства в JavaScript (например, XMLHttpRequest ), это связано с тем, что CORS иногда не выполняет эти запросы. Поскольку я работаю в крупной компании, не так-то просто потребовать, чтобы везде добавлялись правильные заголовки access-control-allow-origin, и, кроме того, у нас есть тестеры, которые загружаются на устройства, запускают прокси и т. д.
Тем не менее, хотя мне удалось найти документацию с некоторым отношением к рассматриваемой задаче, все примеры написаны на C#, и я заметил, что не все, что касается JavaScript, идеально согласуется с этой документацией.
Пользователь Stack Overflow задал очень похожий вопрос здесь, и было принято решение: используйте 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);
},
);
})
);
Вышеприведенный код, казалось, хорошо работал сам по себе, но затем я заметил, что аргументы, передаваемые в функции обратного вызова (аргумент с именем ответа), были не такими, как я ожидал. Я ожидал чего-то, по крайней мере, похожего на ответ 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);
})
);
В заключение, я не думал, что такая простая вещь, как установка порога тайм-аута, будет такой головной болью, но я не смог найти способ сделать это.