事件处理程序仅在以前的事件处理完成时运行

时间:2016-04-14 06:26:20

标签: javascript jquery ajax javascript-events event-handling

附加事件处理程序回调如:

$("someSelector").on('click',callBackHandler);

function callBackHandler(){
   //Some code
   $.ajax({
     //Ajax call with success methods
   })
}

我的成功方法是操纵一些对象属性。由于涉及ajax,它不会等待完成,下一个事件处理将开始。如何确保下次单击事件处理仅在先前处理完成时启动。

无法想到在此使用延迟手动的方法,因为我在for循环的某些条件的基础上手动触发事件(不是一种干净的编码风格,但在特定用例中没有其他选项)。

$('someSelector').trigger('click');

3 个答案:

答案 0 :(得分:1)

$("someSelector").on('click', function(event) {
    event.preventDefault();

    var urAjax = $.ajax({
        // Ajax Call here...
    });

    urAjax.always(function(response) {
        $.when( callBackHandler() ).done(function() {
            // Handle your ajax response in here!
        });
    });
});

function callBackHandler() {
    // Do Stuff 
}

callBackHandler函数将会触发,完成后,你的ajax响应会在此之后直接触发。这允许在callBackHandler函数运行时加载ajax,但在函数完成之前不会触发响应!希望我能理解你在这里要求的东西。

您可以在此处看到一个示例jsfiddle:https://jsfiddle.net/e39oyk8q/11/

尝试在AJAX请求完成之前多次单击“提交”按钮,您会注意到它将在“提交”按钮上一遍又一遍地循环您提供的总点击次数。您可以通过警告框弹出的次数看到这一点,并且在每次调用callBackHandler函数期间,它会向len添加100(在页面上输出)。所以,我确实相信这就是你要求的。

当然,你仍然可以使用:$('someSelector').trigger('click');

修改

另一种方法是返回一个json对象,该对象可以在ajax调用中使用,或者在click事件中的任何位置使用,如下所示:

$("someSelector").on('click', function(event) {
    event.preventDefault();

    var myfunc = callBackHandler();

    var urAjax = $.ajax({
        type: 'POST',
        url: myfunc['url'],
        data: myfunc['data']
    });

    urAjax.always(function(response) {
        $.when( myfunc ).done(function() {
            console.log(myfunc['time']);
            // Handle your ajax response in here!
        });
    });
});

function callBackHandler() {
    var timestamp = new Date().getTime();
    return { url: 'my_ajax_post_url', data: {data1: 'testing', data2: 'testing2'},  time: timestamp }
}

这里的小提琴示例:https://jsfiddle.net/e39oyk8q/15/

答案 1 :(得分:0)

您可以删除函数调用时的绑定,并在ajax为done()时再次绑定。

function callBackHandler(){
    $("someSelector").off('click');
    //Some code
    $.ajax({
        //Ajax call with success methods
    }).done(function(){
        $("someSelector").on('click',callBackHandler);
    })
}

答案 2 :(得分:0)



var requestDataButton = document.querySelector('.js-request-data');
var displayDataBox = document.querySelector('.js-display-data');
var displayOperationsBox = document.querySelector('.js-display-operations');
var displayNumberOfRequestsToDo = document.querySelector('.js-display-number-of-requests-to-do');
var isAjaxCallInProgress = false;
var numberOfAjaxRequestsToDo = 0;
var requestUrl = 'http://jsonplaceholder.typicode.com/photos';

requestDataButton.addEventListener('click', handleClick);

function handleClick() {
    displayNumberOfRequestsToDo.innerText =  numberOfAjaxRequestsToDo;
  numberOfAjaxRequestsToDo++;
  if(!isAjaxCallInProgress) {
    isAjaxCallInProgress = true;
    requestData();
  }
}

function handleResponse(data) {
  displayData(data);
  displayOperationsBox.innerHTML = displayOperationsBox.innerHTML + 'request handled <br>';
  numberOfAjaxRequestsToDo--;
  displayNumberOfRequestsToDo.innerText =  numberOfAjaxRequestsToDo;
  if(numberOfAjaxRequestsToDo) {
    requestData();
  } else {
    isAjaxCallInProgress = false;
  }
}

function displayData(data) {
  displayDataBox.textContent = displayDataBox.textContent + JSON.stringify(data[0]);
}

function requestData() {
  var request = new XMLHttpRequest();
  request.open('GET', requestUrl, true);

  request.onload = function() {
    if (this.status >= 200 && this.status < 400) {
      var data = JSON.parse(this.response);
      handleResponse(data);
    } else {
      // on error
    }
  };

  request.onerror = function() {
    // There was a connection error of some sort
  };

  request.send();
    displayOperationsBox.innerHTML = displayOperationsBox.innerHTML + 'request sent <br>';
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="js-request-data">Request Data</button>
<div>
  <h2>Requests wainting in a queue to be sent:
    <span class="js-display-number-of-requests-to-do">
    0
    </span>
  </h2>
  </div>
<div>
  <h2>Operations:</h2>
  <div class="js-display-operations"></div>
</div>
<div>
  <h2>Response Data:</h2>
  <div class="js-display-data"></div>
</div>
&#13;
&#13;
&#13;

修改

这里是一个实用函数,它接受与$ .ajax类似的参数,然后返回一个增强的$ .ajax函数,该函数会密切关注其先前的调用,并在调度另一个ajax调用之前等待所有先前的请求完成(顺序解雇):

function sequentialize(requestData, responseHandler) {
  let inProgress = false;
  let deferredRequests = 0;
  const makeRequest = () => {
    $.ajax(requestData).then(processManager);
  };
  const processManager = (data) => {
    responseHandler(data);
    if (deferredRequests) {
      deferredRequests--;
      makeRequest();
    } else {
      inProgress = false;
    }
  };

  return function () {
    if (!inProgress) {
      inProgress = true;
      makeRequest();
    } else {
      deferredRequests++;
    }
  };
}