避免全局变量的优雅解决方

时间:2017-11-13 16:00:30

标签: javascript ajax

我正试图找到一种优雅且仍然可读的摆脱全球Var的方法。但找不到办法做到这一点。没有jQuery请它应该没有任何进口工作。



<script>
  var anzahlErg = 0; //<--- THIS ONE

  function ajax(f) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        f(this.responseText);
      }
    };
    xhttp.open("POST", "ajax1.php", true); // SELECT COUNT(*)
    xhttp.send();
  }

  function anfang(response) {
    anzahlErg = response;
  }

  function nachher(response) {
    if (anzahlErg != 0 && response != anzahlErg) {
      location.reload();
    }
  }

  window.onload = ajax(anfang);
  setInterval(function() {
    return ajax(nachher)
  }, 250); //Polling Interval
</script>
&#13;
&#13;
&#13;

4 个答案:

答案 0 :(得分:3)

将所有代码包装在 Immediate Invoked Function Expression 中。这被称为 "module pattern" ,在JS中很常见,因为函数会导致它们自己的范围。

接下来,这一行:

window.onload = ajax(anfang);

遇到ajax(anfang)后会立即运行,而不是等待load事件。它的编写方式如下:&#34;现在运行此函数,它返回的任何函数都应该注册为window.load发生时调用的函数。&#34;相反,你需要将它包装在一个本身就成为处理程序的函数中。

此外,您应该使用.addEventListener()来注册事件处理程序而不是对象属性,例如onload.onreadystatechange

(function(){
  var anzahlErg = 0; //<--- THIS IS NOW LOCAL TO THE IIFE

  function ajax(f) {
    var xhttp = new XMLHttpRequest();

    xhttp.addEventListener("readystatechange", function() {
      if (this.readyState == 4 && this.status == 200) {
        f(this.responseText);
      }
    });

    xhttp.open("POST", "ajax1.php", true); // SELECT COUNT(*)
    xhttp.send();
  }

  function anfang(response) {
    anzahlErg = response;
  }

  function nachher(response) {
    if (anzahlErg != 0 && response != anzahlErg) {
      location.reload();
    }
  }

  window.addEventListener("load", function() {
    ajax(anfang)
  });

  setInterval(function() {
    return ajax(nachher)
  }, 250); //Polling Interval
})();

答案 1 :(得分:0)

无需进行所有编码。只需将值包装在load函数的eventhandler中,就可以将它从全局隐藏起来。注意这不会运行,但至少我在第一个错误后添加了一个clearInterval。 ;)

此示例还使用内置的fetch方法,该方法与promises一起使用并使代码更具可读性。

window.addEventListener('load', function() {
  let results;
  let interval = setInterval(() => {
    fetch('ajax1.php', {
      method: 'POST'
    }).then(response => {
      let count = parseInt(response.text);
      if (results === undefined) {
        results = count;
        return;
      }
      if (results !== count) {
        clearInterval(interval);
        document.location.reload();
      }
    }).catch(() => clearInterval(interval));
  }, 250);
});

有关您原始代码的更多注意事项。 :)

window.onload = ajax(anfang);

这个语句没用,因为它一次执行该函数,所以赋值是无用的,它可以写成:

window.onload = () => ajax(anfang);

您的XMLHttpRequest方法也有点过于冗长,请注意async参数是可选的,默认为true,因此绝对没有理由将其作为参数提供。< / p>

在窗口加载后会执行它,或者您可以使用上面代码中显示的addEventListener

如果计数不同,同样重新加载它似乎资源非常繁重,重新加载现在已经改变的数据不是更好吗?

关于计数功能,如果在轮询间隔中,项目被添加和删除会发生什么?

最后一点,如果您的轮询页面会抛出错误,则会发生许多错误,考虑警告用户轮询不起作用,或者禁用轮询以便用户不继续如果失败则发送请求(可能会提供手动按钮进行刷新,或向用户显示已禁用刷新的消息)。

您最终还可以通过以下方式重写代码

function ajax() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState === 4 && this.status === 200) {
      if (ajax.results === undefined) {
        ajax.results = this.responseText;
      } else if (ajax.results !== this.responseText) {
        document.location.reload();
      }
    }
  };
  xhttp.open("POST", "ajax1.php"); // SELECT COUNT(*)
  xhttp.send();
}

window.addEventListener('load', function() {
  setInterval( ajax, 250 );
});

这使用ajax函数来存储数据,因为函数也是对象。因此,第一次加载数据时,它会设置原始值,下一次,它会将responseText与之前保存为ajax函数属性的值进行比较。

答案 2 :(得分:0)

其他人已经大大改变了你的代码,他们是很好的解决方案,但我想我会介绍闭包以及如何在你的情况下使用它们。

&#13;
&#13;
<script>
  function ajax(f) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        f(this.responseText);
      }
    };
    xhttp.open("POST", "ajax1.php", true); // SELECT COUNT(*)
    xhttp.send();
  }

  function cachedPoll() {
    var anzahlErg = 0;
    return {
      anfang: function anfang(response) {
        anzahlErg = response;
      },
      nachher: function nachher(response) {
        if (anzahlErg != 0 && response != anzahlErg) {
          location.reload();
        }
      }
    };
  }

  var pollers = cachedPoll();
  window.onload = function() {
    ajax(pollers.anfang);
  };
  setInterval(function() {
    return ajax(pollers.nachher)
  }, 250); //Polling Interval
</script>
&#13;
&#13;
&#13;

我还更新了要包含在函数中的onload处理程序,而不是将返回值赋给window.onload

答案 3 :(得分:0)

你可以将属性绑定到你的ajax函数,但真正最干净的方法是使用Scott Marcus的答案。

function ajax(f) {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      f(this.responseText);
    }
  };
  xhttp.open("POST", "ajax1.php", true); // SELECT COUNT(*)
  xhttp.send();
}
ajax.anzahlErg = 0; // This is now a property of the ajax object and not the window object

function anfang(response) {
  ajax.anzahlErg = response;
}

function nachher(response) {
  if (ajax.anzahlErg != 0 && response != ajax.anzahlErg) {
    location.reload();
  }
}

window.onload = ajax(anfang);
  setInterval(function() {
    return ajax(nachher)
}, 250); //Polling Interval