在JavaScript中,有没有一种方法可以向HTTP服务器发送HTTP请求并等待直到服务器响应?我希望我的程序等待直到服务器回复,并且不执行在此请求之后的任何其他命令。如果HTTP服务器宕机,我希望在超时后重复HTTP请求,直到服务器响应,然后程序的执行可以正常继续。
有什么想法吗?
先感谢您, Thanasis
在JavaScript中,有没有一种方法可以向HTTP服务器发送HTTP请求并等待直到服务器响应?我希望我的程序等待直到服务器回复,并且不执行在此请求之后的任何其他命令。如果HTTP服务器宕机,我希望在超时后重复HTTP请求,直到服务器响应,然后程序的执行可以正常继续。
有什么想法吗?
先感谢您, Thanasis
编辑:同步请求现已弃用,您应始终以异步方式处理HTTP请求。
XmlHttpRequest
的open()
有第三个参数,旨在指示您希望该请求是异步的(因此通过onreadystatechange
处理响应)。
因此,如果您希望它是同步的(即等待答案),只需为此第三个参数指定false。
在这种情况下,您可能还想为请求设置有限的timeout
属性,因为它会阻止页面直到接收到响应。
以下是一个包含同步和异步的全功能示例函数:
function httpRequest(address, reqType, asyncProc) {
var req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
if (asyncProc) {
req.onreadystatechange = function() {
if (this.readyState == 4) {
asyncProc(this);
}
};
}
req.open(reqType, address, !(!asyncProc));
req.send();
return req;
}
var req = httpRequest("http://example.com/aPageToTestForExistence.html", "HEAD"); // In this example you don't want to GET the full page contents
alert(req.status == 200 ? "found!" : "failed"); // We didn't provided an async proc so this will be executed after request completion only
$(function() {
$.ajax({
async: false,
// other parameters
});
});
你应该看一下jQuery的AJAX API。我强烈建议使用像jQuery这样的框架来处理这些东西。手动进行跨浏览器的ajax真的很麻烦!
xmlhttp.open("GET","somepage.xml",true);
xmlhttp.onreadystatechange = checkData;
xmlhttp.send(null);
function checkData()
{
alert(xmlhttp.readyState);
}
希望这能有所帮助
对于现代浏览器,我将使用fetch而不是XMLHttpRequest。
async function job() {
const response = await fetch("https://api.ipify.org?format=json", {}) // type: Promise<Response>
if (!response.ok) {
throw Error(response.statusText)
}
return response.text()
}
async function onCommit() {
const result = await job()
// The following will run after the `job` is finished.
console.log(result)
}
<button onclick="onCommit()">Commit</button>
<script>
function onCommit() {
new Promise((resolve, reject) => {
resolve(job1())
}).then(job1Result => {
return job2(job1Result)
}).then(job2Result => {
return job3(job2Result)
}).catch(err => { // If job1, job2, job3, any of them throw the error, then will catch it.
alert(err)
})
}
async function testFunc(url, options) {
// options: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch
const response = await fetch(url, options) // type: Promise<Response>
if (!response.ok) {
const errMsg = await response.text()
throw Error(`${response.statusText} (${response.status}) | ${errMsg} `)
}
return response
}
async function job1() {
console.log("job1")
const response = await testFunc("https://api.ipify.org?format=json", {})
return await response.json()
}
async function job2(job1Data) {
console.log("job2")
console.log(job1Data)
const textHeaders = new Headers()
textHeaders.append('Content-Type', 'text/plain; charset-utf-8')
const options = {"headers": textHeaders}
const response = await testFunc("https://api.ipify.org/?format=text", options)
// throw Error(`test error`) // You can cancel the comment to trigger the error.
return await response.text()
}
function job3(job2Data) {
console.log("job3")
console.log(job2Data)
}
</script>
我在使用Three.js和Google Closure构建的游戏中遇到了类似的情况。我需要加载两个资源,但是Three和Closure不允许我将它们同步加载。
最初我天真地写了以下代码:
main() {
...
var loaded=0;
...
// Load Three geometry
var loader = new THREE.JSONLoader();
loader.load("x/data.three.json", function(geometry) {
...
loaded++;
});
// Load my engine data
goog.net.XhrIo.send("x/data.engine.json", function(e) {
var obj = e.target.getResponseJson();
...
loaded++;
});
// Wait for callbacks to complete
while(loaded<2) {}
// Initiate an animation loop
...
};
等待回调完成的循环从循环的角度来看永远不会结束,因为loaded
从未增加。问题在于,在main
返回之前(至少在Chrome上是这样),回调不会被触发。
一种解决方案可能是让两个回调都检查是否是最后一个完成的,然后继续启动动画循环。
另一种解决方案 - 也许更直接地回答了你所问的问题(如何在启动另一个之前等待每次加载)- 是将回调嵌套如下:
// Load Three geometry
var loader = new THREE.JSONLoader();
loader.load("x/data.three.json", function(geometry) {
...
// Load my engine data
goog.net.XhrIo.send("x/data.engine.json", function(e) {
var obj = e.target.getResponseJson();
...
// Initiate an animation loop
...
});
});
};
为此,您可以在页面开始加载时立即启动JavaScript中的加载程序,然后在请求完成或DOM准备就绪时关闭它。 我的意思是,当页面加载开始时,启动一个加载程序。然后,页面可以使用ajax进行多个同步请求,直到您获得响应为止,请勿关闭加载程序。 在最终调用中收到所需的响应后,您可以关闭加载程序。
async sendRequest() {
const Http = new XMLHttpRequest();
const url='http://localhost:8000/';
Http.open("GET", url);
Http.send();
if (Http.readyState === XMLHttpRequest.DONE) {
return Http;
}
let res;
const p = new Promise((r) => res = r);
Http.onreadystatechange = () => {
if (Http.readyState === XMLHttpRequest.DONE) {
res(Http);
}
}
return p;
}
使用方法
const response = await sendRequest();
const status = response.status;
if (status === 0 || (status >= 200 && status < 400)) {
// The request has been completed successfully
console.log(response.responseText);
} else {
// Oh no! There has been an error with the request!
console.log(`Server Error: ${response.status}`)
}
对于那些使用axios的人,你可以将其包装在一个async
iife中,然后await
它:
(async () => {
let res = await axios.get('https://example.com');
// do stuff with the response
})();
ajaxStop
。 - Joshua Pinter