Javascript 带有Ajax调用的handlign超时
我不是一个JS的家伙(可以写一些基本的东西),我正在将我们的支付API与前端集成,作为过程的一部分,我们希望触发一个超时,以防我的后端支付API在给定的时间范围内没有响应。下面是与支付API交互的JS代码Javascript 带有Ajax调用的handlign超时,javascript,jquery,ajax,typescript,javascript-objects,Javascript,Jquery,Ajax,Typescript,Javascript Objects,我不是一个JS的家伙(可以写一些基本的东西),我正在将我们的支付API与前端集成,作为过程的一部分,我们希望触发一个超时,以防我的后端支付API在给定的时间范围内没有响应。下面是与支付API交互的JS代码 performAuthorizePaymentRequest: function (payment) { return new Promise(function (resolve, reject) { $.ajax({ t
performAuthorizePaymentRequest: function (payment) {
return new Promise(function (resolve, reject) {
$.ajax({
type: 'POST',
url: encodedContextPath + '/checkout/authorise_order',
data: JSON.stringify(payment),
dataType: 'json',
contentType: 'application/json',
success: resolve,
error: reject,
always: function () {
pageSpinner.end()
},
timeout: 30000 /* call this.session.completePayment() within 30 seconds or the payment is cancelled */
});
});
}
这似乎很好,但我看到了以下问题
注意:此代码将仅执行Safari,对于其他浏览器,此代码不可用我将避免ajax调用中出现超时,但将使用php中的
设置时间限制(30)
(如果您的/checkout/authorize\u订单是php…)
var check = false;
setInterval(function() {
if (check === true) {
return;
}
$.ajax({
type: 'POST',
url: encodedContextPath + '/checkout/authorise_order',
data: JSON.stringify(payment),
dataType: 'json',
contentType: 'application/json',
success: function(e) {
if (e.status === 200) {
check = true;
}
},
always: function() {
pageSpinner.end()
}
});
}, 10);
如果答案提前到达,一切正常(不会等到30秒)这是一个时间限制
对于javascript部分,我使用自己的:
function ajaxLive ( divID ) {
var pcache = (Math.floor(Math.random() * 100000000) + 1);
var params = "divID="+encodeURIComponent(divID);
var xhr = new XMLHttpRequest();
xhr.open("POST", "path_to_script.php?pcache="+pcache, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onprogress = function(e) { if (xhr.readyState == 4) { $("#"+divID).html(e.currentTarget.responseText) ; } }
xhr.send(params);
}
在这个函数中,pcache
if对于避免缓存至关重要,因为api调用的目的是每次都有不同的答案
在params
中,您也可以添加额外的内容,并将其传递给php
如果您使用php curl或shell curl,那么还有max-time机制
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); // for the connection (not the answer)
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //timeout in seconds
- 我将向您推荐一些我不知道您是否喜欢或是否适合您的东西,但您可以使用
方法此方法将自动重复您的代码多次如果发生事件,您可以创建条件停止此setInterval()
函数setInterval()
var check = false;
setInterval(function() {
if (check === true) {
return;
}
$.ajax({
type: 'POST',
url: encodedContextPath + '/checkout/authorise_order',
data: JSON.stringify(payment),
dataType: 'json',
contentType: 'application/json',
success: function(e) {
if (e.status === 200) {
check = true;
}
},
always: function() {
pageSpinner.end()
}
});
}, 10);
你可以像这样中止超时吗?这个例子是错误的,但是你可以在成功的时候做同样的事情
$.ajax({
url: "/your_ajax_method/",
type: "GET",
dataType: "json",
timeout: 3000, //Set your timeout value in milliseconds or 0 for unlimited
success: function(response) { alert(response); },
error: function(jqXHR, textStatus, errorThrown) {
if(textStatus!=="timeout")
jqXHR.abort("timeout");
}
})); 我建议使用fetch而不是ajax,因为默认情况下它会在300秒后超时,如果服务器返回错误,它就会失败 您还可以使用中止控制器在默认超时之前中止请求 fetch中的相同代码为:
const performAuthorizePaymentRequest=(付款)=>
获取(`encodedContextPath}/checkout/authorize\u order`{
方法:“POST”,
标题:{
“内容类型”:“应用程序/json”
},
正文:JSON.stringify(支付),
}).然后(r=>{
pageSpinner.end();
返回r.json();
})
您可以使用XMLHttpRequest
对象的abort
方法,然后设置超时以在30秒后中止请求。像这样:
var requestObj = $.ajax({
...
)};
setTimeout(function(){
requestObj.abort();
}, 30 * 1000); // 30 seconds
看
另一种方法是通过将状态标志设置为“超时”,使
success
功能在30秒后停止工作。请参见下面代码中的注释:
/* Use this variable to check whether we are within 30 minutes. This can be:
'still in time': the original state, waiting for a response
'out of time': we passed the 30 minutes, don't do anything with a possible success response and call the reject function
'already resolved': resolved within 30 minutes, no need to reject after 30 minutes
*/
var timeStatus = 'still in time';
/* Time until timeout */
var timeoutTime = 30 * 1000; //30 seconds
/* Save the request */
var theRequest = $.ajax({
...
/* In success we must check if we are still in time */
success: function(data, textStatus, jqXHR){
if(timeStatus === 'out of time'){
// BAIL OUT. Do nothing since this has alreay been rejected in the setTimeout function. */
console.log("bailing out. 30 minutes exceeded");
return false;
}
else{
/* Set to 'already resolved' so our setTimeout function doesn't reject. */
timeStatus = 'already resolved';
resolve(data, textStatus, jqXHR);
}
},
/* In error we do the same 'out of time' check */
error: function (jqXHR, errorCode, error){
if(timeStatus === 'out of time'){
// BAIL OUT. Do nothing since the request has alreay been rejected in the setTimeout function. */
console.log("bailing out. 30 minutes exceeded");
return false;
}
else{
/* Set to 'already resolved' so our setTimeout function doesn't reject. */
timeStatus = 'already resolved';
reject(jqXHR, errorCode, error);
}
}
});
/* After 30 minutes set the timeStatus to 'out of time' so we can cut off incoming ajax responses. */
setTimeout(function(){
if(timeStatus !== 'already resolved'){
timeStatus = 'out of time';
reject(theRequest, 'timeout','');
}
}, timeoutTime);
您可以使用promise.race()
race()方法返回满足或拒绝的承诺
一旦iterable中的一个承诺实现或拒绝,
具有该承诺的价值或理由
例如:
const timeout = (prom, time) =>
Promise.race([prom, new Promise((_r, rej) => setTimeout(rej, time))]);
使用:
ref:应该是30秒而不是30分钟,但你的第一个方法是最好/最简单的答案。我的错。我编辑了答案,也许你可以考虑把这个标记为被接受的答案。
// resolves in 500 ms
const fn = async () => {
await new Promise((res) => setTimeout(res, 500));
return "p2";
}
// finishes before the timeout
const result = await timeout(fn(), 1000);
// result = p2
// timeouts in 100 ms
await timeout(fn(), 100);
// error