Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 带有Ajax调用的handlign超时_Javascript_Jquery_Ajax_Typescript_Javascript Objects - Fatal编程技术网

Javascript 带有Ajax调用的handlign超时

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

我不是一个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 */
            });
       });
    }
这似乎很好,但我看到了以下问题

  • 如果m backed API抛出任何错误,代码仍在等待超时
  • 即使在成功的情况下,js也会在显示成功消息之前等待超时
  • 有办法解决这个问题吗?如果我在这里做错了什么,请告诉我


    注意:此代码将仅执行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