我可以在事件处理程序执行时停止它吗?

时间:2017-10-11 04:00:14

标签: javascript dom-events

是否可以在再次调用事件时停止执行上一个事件?

为了澄清,我有一个按钮<button onclick='load()'>load</button>,它调用一个load()函数来获取一个数组,处理每个元素并将其显示在列表<ul id='main'></ul>

function load(event) {
            $("#main").empty();               //empty old elements
            $.get("load.php", '', function (data) {
                var arr = JSON.parse(data);
                for (i = 0; i < arr.length; ++i) {
                    process(arr[I]);          //process and append to #main
                }
            });
        }

问题是,如果我仍然将元素放入数组中时再次单击该按钮,我会获得新列表以及旧列表的其余部分。

有没有办法在第一个事件仍在执行但仍然执行第二个事件时停止第一个事件?

4 个答案:

答案 0 :(得分:0)

如上所述,您可以通过设置标志并检查它来停止事件,但更好的方法是直接分配新值。如果您的代码有效,则意味着JSON.parse已经返回一个数组。

这意味着

"use strict";
(function () {
    function load(event) {
        $("#main").empty();
        $.get("load.php", '', function (data) {
            process = JSON.parse(data);
            $("#main").whateverMethodFillsTheElement(process);
        });
}());

此外,在编写发出HTTP请求的异步JavaScript代码时,promises优先于回调。由于$.get返回Promise,您可以写

"use strict";
(function () {
    function load(event) {
        $("#main").empty();
        $.get("load.php")
            .then(function (data) {
                var items = JSON.parse(data);
                $("#main").whateverMethodFillsTheElement(items);
            });
    }
}());

正如评论中所讨论的,目的是在另一个请求中使用每个项目,这些请求提供了添加到主要内容的实际值。因此,加载数据会触发每个已加载项的异步调用。

为了适应这种情况,我们需要确定一个 key 字段,我们可以用它来跟踪每个项目,因此我们不会将现有项目附加到列表中。为了便于说明,我们将此字段称为id

"use strict";
(function () {
    var allItems = [];

    function load(event) {
        $("#main").empty();
        $.get("load.php")
            .then(function (data) {
              return JSON.parse(data);
            })
            .then(function (items) {
              items.forEach(item => {
                processItem(item)
                  .then(function (processed) {
                    var existingItem = allItems.filter(i => i.id === item.id)[0];
                    if(existingItem) {
                      var existingIndex = allItems.indexOf(existingItem);
                      allItems[existingIndex] = processed;
                    } 
                    else {
                      allItems.push(processed);
                    }
                  });
              });
          });
    }
}());

答案 1 :(得分:0)

你应该试试这个:

var xhr;
function load(ev){
  if(ev.eventPhase === 2){
    if(xhr)xhr.abort();
    $('#main').empty(); 
    xhr = $.get('load.php', function(data){
      var a = JSON.parse(data);
      for(var i=0,l=a.length; i<l; i++){
        process(a[i]);
      }
    });
  }
}

答案 2 :(得分:0)

我错了,但是......

var req = $.ajax({
        $("#main").addEventListener("click",()=>{req.abort()})
        ...
        ...
        $("#main").removeEventListener("click",()=>{req.abort()})
    });

答案 3 :(得分:0)

好吧,似乎无法在开始执行后停止Ajax成功功能,或者在不中止当前事件的情况下停止过去的事件。 但是下面的解决方案对我有用,所以我想我会在这里发布它:

var num = 0;
function load() {
    var curNum = ++num;
    $("#main").empty();               
    $.get("load.php", '', function (data) {
        var arr = JSON.parse(data);
        for (i = 0; i < arr.length; ++i) {
            process(arr[i], curNum); 
        }
    });
}
function process(item, curNum) {
    if(curNum === num) {  //don't process if a new request has been made
        //get 'data' based on 'item'...
        if(curNum === num) {  //check again in case a new request was made in the meantime
            $("#main").append(data);
        }
    }
}

感谢大家的帮助。