Мне нужно выполнить запрос HTTP GET в JavaScript. Как лучше всего это сделать?
Мне нужно сделать это в виджете дашкода Mac OS X.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вот код, чтобы сделать это напрямую с помощью JavaScript. Но, как упоминалось ранее, вам будет намного лучше с библиотекой JavaScript. Мой любимый - jQuery.
В приведенном ниже случае вызывается страница ASPX (обслуживающая REST-сервис для бедняков) для возврата объекта JSON JavaScript.
var xmlHttp = null;
function GetCustomerInfo()
{
var CustomerNumber = document.getElementById( "TextBoxCustomerNumber" ).value;
var Url = "GetCustomerInfoAsJson.aspx?number = " + CustomerNumber;
xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = ProcessRequest;
xmlHttp.open( "GET", Url, true );
xmlHttp.send( null );
}
function ProcessRequest()
{
if ( xmlHttp.readyState == 4 && xmlHttp.status == 200 )
{
if ( xmlHttp.responseText == "Not found" )
{
document.getElementById( "TextBoxCustomerName" ).value = "Not found";
document.getElementById( "TextBoxCustomerAddress" ).value = "";
}
else
{
var info = eval ( "(" + xmlHttp.responseText + ")" );
// No parsing necessary with JSON!
document.getElementById( "TextBoxCustomerName" ).value = info.jsonData[ 0 ].cmname;
document.getElementById( "TextBoxCustomerAddress" ).value = info.jsonData[ 0 ].cmaddr1;
}
}
}
Поскольку этот ответ является одним из лучших результатов поиска в Google "http-запрос javascript", стоит упомянуть, что запуск eval для таких данных ответа считается плохой практикой.
@Kloar - хороший аргумент, но было бы еще лучше объяснить причину, по которой это плохо, я думаю, это безопасность. Объяснение того, почему практика плохая, - лучший способ заставить людей изменить свои привычки.
Прототип упрощает работу
new Ajax.Request( '/myurl', {
method: 'get',
parameters: { 'param1': 'value1'},
onSuccess: function(response){
alert(response.responseText);
},
onFailure: function(){
alert('ERROR');
}
});
Проблема в том, что Mac OS X не поставляется с предустановленным Prototype. Поскольку виджет должен запускаться на любом компьютере, включение Prototype (или jQuery) в каждый виджет - не лучшее решение.
@kiamlaluno использовать Prototype cdn от cloudflare
$.get(
"somepage.php",
{paramOne : 1, paramX : 'abc'},
function(data) {
alert('page content: ' + data);
}
);
обратите внимание, что это не работает в IE 10 при попытке доступа к URL-адресу в другом домене, чем домен страницы.
@BornToCode, вам следует продолжить расследование и, возможно, открыть ошибку в трекере проблем jQuery в этом случае
Я знаю, что некоторые люди хотят писать чистый Javascript. Я понимаю. У меня нет проблем с тем, что люди делают это в своих проектах. Мое «In jQuery:» следует интерпретировать как «Я знаю, что вы спрашивали, как это сделать в Javascript, но позвольте мне показать вам, как вы это сделаете с помощью jQuery, чтобы у вас могло возникнуть любопытство, увидев, какой вид синтаксической краткости и ясность, которую вы можете получить, используя эту библиотеку, которая также предоставит вам множество других преимуществ и инструментов ".
Также обратите внимание, что на оригинальном плакате позже было сказано: «Спасибо за все ответы! Я выбрал jQuery, основываясь на некоторых вещах, которые я прочитал на их сайте».
IE будет кэшировать URL-адреса, чтобы ускорить загрузку, но если вы, скажем, опрашиваете сервер через определенные промежутки времени, пытаясь получить новую информацию, IE будет кэшировать этот URL-адрес и, вероятно, вернет тот же набор данных, который у вас всегда был.
Независимо от того, как вы в конечном итоге выполняете свой GET-запрос - обычный JavaScript, Prototype, jQuery и т. д. - убедитесь, что вы создали механизм для борьбы с кешированием. Чтобы бороться с этим, добавьте уникальный токен в конец URL-адреса, по которому вы собираетесь попасть. Это можно сделать:
var sURL = '/your/url.html?' + (new Date()).getTime();
Это добавит уникальную метку времени в конец URL-адреса и предотвратит кеширование.
В файле Info.plist вашего виджета не забудьте установить для ключа AllowNetworkAccess значение true.
Лучше всего использовать AJAX (вы можете найти простое руководство на этой странице Тизаг). Причина в том, что любой другой метод, который вы можете использовать, требует большего количества кода, он не гарантирует работу в кросс-браузере без переделки и требует, чтобы вы использовали больше клиентской памяти, открывая скрытые страницы внутри фреймов, передавая URL-адреса, анализируя их данные и закрывая их. В этой ситуации можно использовать AJAX. Это мои два года тяжелой разработки javascript.
Я не знаком с виджетами Dashcode в Mac OS, но если они позволяют использовать библиотеки JavaScript и поддерживают XMLHttpRequests, я бы использовал jQuery и сделал бы что-то вроде этого:
var page_content;
$.get( "somepage.php", function(data){
page_content = data;
});
Если вы хотите использовать код для виджета Dashboard и не хотите включать библиотеку JavaScript в каждый созданный виджет, вы можете использовать объект XMLHttpRequest, который изначально поддерживается Safari.
Как сообщил Эндрю Хеджес, виджет по умолчанию не имеет доступа к сети; вам нужно изменить этот параметр в info.plist, связанном с виджетом.
Браузеры (и Dashcode) предоставляют объект XMLHttpRequest, который можно использовать для выполнения HTTP-запросов из JavaScript:
function httpGet(theUrl)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
xmlHttp.send( null );
return xmlHttp.responseText;
}
Однако синхронные запросы не приветствуются и будут генерировать предупреждение в следующем виде:
Note: Starting with Gecko 30.0 (Firefox 30.0 / Thunderbird 30.0 / SeaMonkey 2.27), synchronous requests on the main thread have been deprecated due to the negative effects to the user experience.
Вы должны сделать асинхронный запрос и обработать ответ внутри обработчика событий.
function httpGetAsync(theUrl, callback)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
Это аккуратно, однако обратите внимание, что IE 10 выдает предупреждение системы безопасности при использовании этого и попытке получить доступ к URL-адресу в другом домене, чем домен страницы.
Ну, конечно, он встроен в Javascript, или как какая-нибудь библиотека Javascript может предложить для этого удобный метод? Разница в том, что удобные методы предлагают, ну, удобство и более ясный и простой синтаксис.
Префикс XML, потому что он использует X из AJAX ~ Асинхронный JavaScript и XML. Кроме того, хороший аргумент относительно "API с привязкой к ECMAScript" связан с тем, что JavaScript может использоваться во многих вещах, кроме браузеров, поддерживающих HTTP (например, Adobe Reader ...). Хорошо, что нужно помнить, так что снимайте шляпу перед PointedEars.
@ AlikElzin-kilaka: есть веская причина, см. этот раздел спецификации W3, где объясняется название. Google - ваш друг;)
@ AlikElzin-kilaka На самом деле все ответы выше неуместны (фактически, связанные документы W3 объясняют, что «каждый компонент этого имени потенциально вводит в заблуждение»). Правильный ответ? это просто плохо названо stackoverflow.com/questions/12067185/…
Внимание: с этой функцией ваш обратный вызов никогда не будет отозван, если страница ответит на что-либо, кроме состояния 200 OK.
Почему это вызывает CORS? Я думал, что запросы GET не должны запускать его?
Например, символы типа >> & << закодированы в% 26 ??
@HeroCC - Вы ошиблись. Любой запрос ajax с разными источниками подчиняется одной и той же политике происхождения.
зачем нам xmlHttp.send(null);. что это означает?
что делать, если код вызывается в $ .ajax? синхронный по-прежнему устарел?
получить API предлагает лучший способ сделать это и может быть полифиллирован при необходимости (см. @ PeterGibson ответ ниже).
Версия без обратного вызова
var i = document.createElement("img");
i.src = "/your/GET/url?params=here";
Превосходно! Мне нужен сценарий Greasemonkey, чтобы поддерживать сеанс, и этот фрагмент идеален. Просто завернул в вызов setInterval.
как мне получить результат?
@ user4421975 Вы не получите - чтобы получить доступ к ответу на запрос, вам нужно вместо этого использовать вышеупомянутый XMLHttpRequest.
Выше было много отличных советов, но они не очень пригодны для повторного использования и слишком часто наполнены ерундой DOM и прочей ерундой, скрывающей простой код.
Вот созданный нами класс Javascript, который можно использовать повторно и легко использовать. В настоящее время у него есть только метод GET, но он работает для нас. Добавление POST не должно утомлять ничьих навыков.
var HttpClient = function() {
this.get = function(aUrl, aCallback) {
var anHttpRequest = new XMLHttpRequest();
anHttpRequest.onreadystatechange = function() {
if (anHttpRequest.readyState == 4 && anHttpRequest.status == 200)
aCallback(anHttpRequest.responseText);
}
anHttpRequest.open( "GET", aUrl, true );
anHttpRequest.send( null );
}
}
Использовать его так же просто, как:
var client = new HttpClient();
client.get('http://some/thing?with=arguments', function(response) {
// do something with response
});
Ошибка UnCaughtReference, HttpClient не определен. Я сам получаю эту первую строчку.
Как вы это называете из html onClick?
Создайте функцию еще там, где она содержит клиент var ... и просто запустите functionName (); вернуть ложь; в onClick
ReferenceError: XMLHttpRequest is not definedA copy-paste modern version ( using fetch and arrow function ) :
//Option with catch
fetch( textURL )
.then(async r=> console.info(await r.text()))
.catch(e=>console.error('Boo...' + e));
//No fear...
(async () =>
console.info(
(await (await fetch( jsonURL )).json())
)
)();
A copy-paste classic version:
let request = new XMLHttpRequest();
request.onreadystatechange = function () {
if (this.readyState === 4) {
if (this.status === 200) {
document.body.className = 'ok';
console.info(this.responseText);
} else if (this.response == null && this.status === 0) {
document.body.className = 'error offline';
console.info("The computer appears to be offline.");
} else {
document.body.className = 'error';
}
}
};
request.open("GET", url, true);
request.send(null);
Получить HTTP-запрос GET можно двумя способами:
Этот подход основан на формате xml. Вы должны передать URL-адрес запроса.
xmlhttp.open("GET","URL",true);
xmlhttp.send();
Этот основан на jQuery. Вы должны указать URL-адрес и имя_функции, которое вы хотите вызвать.
$("btn").click(function() {
$.ajax({url: "demo_test.txt", success: function_name(result) {
$("#innerdiv").html(result);
}});
});
Для тех, кто использует AngularJs, это $http.get:
$http.get('/someUrl').
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
function get(path) {
var form = document.createElement("form");
form.setAttribute("method", "get");
form.setAttribute("action", path);
document.body.appendChild(form);
form.submit();
}
get('/my/url/')
То же самое можно сделать и для почтового запроса. Взгляните на эту ссылку Запрос на отправку JavaScript как отправка формы
Новый window.fetch API - это более чистая замена XMLHttpRequest, в которой используются обещания ES6. Есть хорошее объяснение здесь, но оно сводится к (из статьи):
fetch(url).then(function(response) {
return response.json();
}).then(function(data) {
console.info(data);
}).catch(function() {
console.info("Booo");
});
Поддержка браузера теперь хорош в последних выпусках (работает в Chrome, Firefox, Edge (v14), Safari (v10.1), Opera, Safari iOS (v10.3), браузере Android и Chrome для Android), однако IE, скорее всего, будет не получить официальную поддержку. Доступен GitHub имеет полифил, который рекомендуется для поддержки старых браузеров, которые все еще широко используются (особенно версии Safari до марта 2017 г. и мобильные браузеры того же периода).
Думаю, удобнее ли это jQuery или XMLHttpRequest или нет, зависит от характера проекта.
Вот ссылка на спец https://fetch.spec.whatwg.org/
Редактировать:
Используя ES7 async / await, это становится просто (на основе этот Gist):
async function fetchAsync (url) {
let response = await fetch(url);
let data = await response.json();
return data;
}
Я мог бы сэкономить время, упомянув, что вы можете сделать это, чтобы включить учетные данные в запрос: fetch(url, { credentials:"include" })
@ bugmenot123 window.fetch не поставляется с анализатором XML, но вы можете проанализировать ответ самостоятельно, если обработаете его как текст (не json, как в примере выше). См. Пример stackoverflow.com/a/37702056/66349
Одно решение, поддерживающее старые браузеры:
function httpRequest() {
var ajax = null,
response = null,
self = this;
this.method = null;
this.url = null;
this.async = true;
this.data = null;
this.send = function() {
ajax.open(this.method, this.url, this.asnyc);
ajax.send(this.data);
};
if (window.XMLHttpRequest) {
ajax = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP.6.0");
}
catch(e) {
try {
ajax = new ActiveXObject("Msxml2.XMLHTTP.3.0");
}
catch(error) {
self.fail("not supported");
}
}
}
if (ajax == null) {
return false;
}
ajax.onreadystatechange = function() {
if (this.readyState == 4) {
if (this.status == 200) {
self.success(this.responseText);
}
else {
self.fail(this.status + " - " + this.statusText);
}
}
};
}
Может быть, несколько излишне, но вы определенно будете осторожны с этим кодом.
Использование:
//create request with its porperties
var request = new httpRequest();
request.method = "GET";
request.url = "https://example.com/api?parameter=value";
//create callback for success containing the response
request.success = function(response) {
console.info(response);
};
//and a fail callback containing the error
request.fail = function(error) {
console.info(error);
};
//and finally send it away
request.send();
Не могли бы люди прокомментировать, что я сделал не так? В этом смысле не очень полезно!
На мой взгляд, лучший ответ, если кодировать в ES5 с использованием простого javascript.
Вы можете сделать это и с чистым JS:
// Create the XHR object.
function createCORSRequest(method, url) {
var xhr = new XMLHttpRequest();
if ("withCredentials" in xhr) {
// XHR for Chrome/Firefox/Opera/Safari.
xhr.open(method, url, true);
} else if (typeof XDomainRequest != "undefined") {
// XDomainRequest for IE.
xhr = new XDomainRequest();
xhr.open(method, url);
} else {
// CORS not supported.
xhr = null;
}
return xhr;
}
// Make the actual CORS request.
function makeCorsRequest() {
// This is a sample server that supports CORS.
var url = 'http://html5rocks-cors.s3-website-us-east-1.amazonaws.com/index.html';
var xhr = createCORSRequest('GET', url);
if (!xhr) {
alert('CORS not supported');
return;
}
// Response handlers.
xhr.onload = function() {
var text = xhr.responseText;
alert('Response from CORS request to ' + url + ': ' + text);
};
xhr.onerror = function() {
alert('Woops, there was an error making the request.');
};
xhr.send();
}
См .: подробнее: html5rocks руководство
Коротко и чисто:
const http = new XMLHttpRequest()
http.open("GET", "https://api.lyrics.ovh/v1/toto/africa")
http.send()
http.onload = () => console.info(http.responseText)Чтобы обновить лучший ответ от Джоанн с обещанием, это мой код:
let httpRequestAsync = (method, url) => {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (xhr.status == 200) {
resolve(xhr.responseText);
}
else {
reject(new Error(xhr.responseText));
}
};
xhr.send();
});
}
Для этого рекомендуется использовать Fetch API с использованием обещаний JavaScript. XMLHttpRequest (XHR), объект IFrame или динамические теги являются более старыми (и более громоздкими) подходами.
<script type=“text/javascript”>
// Create request object
var request = new Request('https://example.com/api/...',
{ method: 'POST',
body: {'name': 'Klaus'},
headers: new Headers({ 'Content-Type': 'application/json' })
});
// Now use it!
fetch(request)
.then(resp => {
// handle response })
.catch(err => {
// handle errors
}); </script>
Вот отличные получить демо и Документы MDN
Простой асинхронный запрос:
function get(url, callback) {
var getRequest = new XMLHttpRequest();
getRequest.open("get", url, true);
getRequest.addEventListener("readystatechange", function() {
if (getRequest.readyState === 4 && getRequest.status === 200) {
callback(getRequest.responseText);
}
});
getRequest.send();
}
Вот альтернатива файлам xml, позволяющая загружать файлы как объект и очень быстро получать доступ к свойствам как объекту.
XML работает как дерево, ладно? вместо того, чтобы писать
<property> value <property>
напишите такой простой файл:
Property1: value
Property2: value
etc.
Сохраните файл .. Теперь вызовите функцию ....
var objectfile = {};
function getfilecontent(url){
var cli = new XMLHttpRequest();
cli.onload = function(){
if ((this.status == 200 || this.status == 0) && this.responseText != null) {
var r = this.responseText;
var b=(r.indexOf('\n')?'\n':r.indexOf('\r')?'\r':'');
if (b.length){
if (b=='\n'){var j=r.toString().replace(/\r/gi,'');}else{var j=r.toString().replace(/\n/gi,'');}
r=j.split(b);
r=r.filter(function(val){if ( val == '' || val == NaN || val == undefined || val == null ){return false;}return true;});
r = r.map(f => f.trim());
}
if (r.length > 0){
for(var i=0; i<r.length; i++){
var m = r[i].split(':');
if (m.length>1){
var mname = m[0];
var n = m.shift();
var ivalue = m.join(':');
objectfile[mname]=ivalue;
}
}
}
}
}
cli.open("GET", url);
cli.send();
}
теперь вы можете эффективно получать свои ценности.
getfilecontent('mesite.com/mefile.txt');
window.onload = function(){
if (objectfile !== null){
alert (objectfile.property1.value);
}
}
Это всего лишь небольшой подарок для группы. Спасибо за лайк :)
Если вы хотите протестировать функцию на своем ПК локально, перезапустите браузер с помощью следующей команды (поддерживается всеми браузерами, кроме Safari):
yournavigator.exe '' --allow-file-access-from-files
// Create a request variable and assign a new XMLHttpRequest object to it.
var request = new XMLHttpRequest()
// Open a new connection, using the GET request on the URL endpoint
request.open('GET', 'restUrl', true)
request.onload = function () {
// Begin accessing JSON data here
}
// Send request
request.send()
<button type = "button" onclick = "loadXMLDoc()"> GET CONTENT</button>
<script>
function loadXMLDoc() {
var xmlhttp = new XMLHttpRequest();
var url = "<Enter URL>";``
xmlhttp.onload = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == "200") {
document.getElementById("demo").innerHTML = this.responseText;
}
}
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
</script>
Современный, чистый и самый короткий
fetch('https://www.randomtext.me/api/lorem')
let url = 'https://www.randomtext.me/api/lorem';
// to only send GET request without waiting for response just call
fetch(url);
// to wait for results use 'then'
fetch(url).then(r=> r.json().then(j=> console.info('\nREQUEST 2',j)));
// or async/await
(async()=>
console.info('\nREQUEST 3', await(await fetch(url)).json())
)();Open Chrome console network tab to see request
Обратите внимание, что это регулируется той же политикой происхождения. en.wikipedia.org/wiki/Same_origin_policy