XMLHttpRequest.onreadystatechange表现得很奇怪

时间:2017-05-19 14:11:51

标签: javascript

我有一个名为urlExists的函数,我在几个项目中使用没有问题。现在我在患者面板中,需要在调用函数addEventListener之前检查是否存在js文件:

function urlExists(url){
   var http = new XMLHttpRequest();
   http.open('HEAD', url, false);
   http.onreadystatechange = function(){
       if(request.readyState==4){
           return true;
       }else{
           return false;
       }
   }
}
//other part of code

   if (urlExists('../../medvoice/speaker.js')){
      beep.addEventListener('ended', function() {
       var parameters = {
         target: dados,
         tts: {
            name: 'lianetts'
         },
         binder: 'speak',
          path: {
           name: '../../medvoice/mediapool/',
           link: '/medhosphsl/medvoice/mediapool/'
         }
       };                                                                                                                                               
       var speaker = new Speaker(parameters);
    });
   }

当一个put控制台登录urlExists时,控制台会显示测试短语,但是在onreadystatechange里面没有。我错过了什么?

1 个答案:

答案 0 :(得分:2)

有几个问题:

  1. 您的return truereturn false未从urlExists返回,他们正在从onreadystatechange回调中返回。 urlExists在任何地方都没有明确return,因此调用它始终会生成undefined

  2. 您永远不会致电send来解除请求。

  3. 您正在使用readyState来确定资源是否存在,但这只是告诉您请求的状态;你应该检查status

  4. 如果必须使用同步请求,则根本不需要或不需要onreadystatechange处理程序。这是一个涉及所有这些问题的版本:

    function urlExists(url){
       var http = new XMLHttpRequest();
       http.open('HEAD', url, false);
       http.send();
       return http.status === 200;
    }
    

    为了完整性:同步ajax请求会导致用户体验不佳,并且很可能在某些时候完全被淘汰。相反,使用异步请求并让urlExists返回一个承诺:

    function urlExists(url){
        return new Promise(function(resolve) {
            var http = new XMLHttpRequest();
            http.open('HEAD', url);
            http.onreadystatechange = function() {
                if (http.readyState === 4) {
                    resolve(http.status === 200);
                }
            };
            http.send();
        });
    }
    
    // Usage:
    urlExists("some-url").then(function(exists) {
        console.log("Exists? " + exists);
    });
    

    使用fetch和ES2015 +箭头功能的更现代的方式:

    function urlExists(url) {
        return fetch(url, {method: "HEAD"}).then(response => response.ok);
    }
    
    // Usage:
    urlExists("some-url").then(exists => console.log("Exists? " + exists));
    

    或者我们可以接受ES2017(下个月出局!):

    async function urlExists(url) {
        return (await fetch(url, {method: "HEAD"})).ok;
    }
    
    // Usage (in another async function):
    console.log("Exists? " + await urlExists("some-url"));
    

    附注:urlExists仅适用于您可以通过ajax访问的网址,因此通常只适用于同一来源的网址。如果这是你的用例,那很好,但我想我会提到它。