[英]handlign timeout with Ajax call
我不是 JS 人(可以写一些基本的东西),我正在努力将我们的付款 API 与前端集成,作为该过程的一部分,我们想触发超时以防我的后端付款 API 没有响应在给定的时间范围内。 这是与付款 API 交互的 JS 代码。
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,其他浏览器不可用
您可以使用XMLHttpRequest
object 的abort
方法,然后设置超时以在 30 秒后中止请求。 像这样:
var requestObj = $.ajax({
...
)};
setTimeout(function(){
requestObj.abort();
}, 30 * 1000); // 30 seconds
另一种方法是通过将状态标志设置为“超时”来让success
的 function 在 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);
I would avoid a timeout in the ajax call, but would go to a with a set_time_limit(30)
in the php (if your /checkout/authorise_order is a php...)
如果答案在之前到达,一切都很好(不会等到 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);
}
在这个 function pcache
中,如果避免缓存至关重要,因为 api 调用的目的是每次都有不同的答案......
在params
中你也可以添加额外的东西,它会将它传递给 php
如果您使用 php curl 或 shell ZF6E57C9DE709E45FEB540D955351F 机制,还有最大时间机制,
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0); // for the connection (not the answer)
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //timeout in seconds
你可以像这样中止超时吗? 这个例子有错误,但你可以在成功时做同样的事情
$.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 秒后超时,并且如果服务器返回错误则会失败。
您还可以使用 abort controller https://developer.mozilla.org/en-US/docs/Web/API/AbortController在默认超时之前中止请求。
fetch 中的相同代码是:
const performAuthorizePaymentRequest = (payment) =>
fetch(`${encodedContextPath}/checkout/authorise_order`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payment),
}).then(r=>{
pageSpinner.end();
return r.json();
})
performAuthorizePaymentRequest: function (payment) {
// you can start a loading on your view in here like this
// $('.fix-loading').show('fast');
let promises_await = [];
promises_await.push(
$.ajax({
type: 'POST',
url: encodedContextPath + '/checkout/authorise_order',
data: JSON.stringify(payment),
dataType: 'json',
contentType: 'application/json',
success: resolve,
error: reject,
// I don't know are these lines below are necessary for your payment or not
//always: function () {
// pageSpinner.end()
//},
//timeout: 30000 /* call this.session.completePayment() within 30 seconds or the payment is cancelled */
});
);
$.when.apply($, promises_await).then(function () {
// if all requests in ajax complete and receive answer, do something here
// also if use loading you can hide it here like this and also in catch
// $('.fix-loading').hide('fast');
}).catch(function () {
// also if use loading you can hide it here like this and also in catch
// $('.fix-loading').hide('fast');
//error handling
});
}
您可以使用 promise.race()。
Promise.race() 方法返回一个 promise,一旦可迭代中的一个承诺履行或拒绝,就会履行或拒绝,其值或原因来自该 promise。
例子:
const timeout = (prom, time) =>
Promise.race([prom, new Promise((_r, rej) => setTimeout(rej, time))]);
利用:
// 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
参考: 匿名棒。com
setInterval()
方法,这个方法会自动重复你的代码很多次,如果事件发生停止,你可以创建一个条件这个setInterval()
function例子
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);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.