我有一个名为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);
    });
   }


当在urlExists内放一个控制台日志时,控制台会显示测试短语,但在onreadystatechange里面却不会。我丢失了什么?

最佳答案

有几个问题:


您的return truereturn false不是从urlExists返回的,而是从onreadystatechange回调返回的。 urlExists在任何地方都没有显式的return,因此调用它总是导致undefined
您永远不会调用send来触发请求。
您正在使用readyState来确定资源是否存在,但这只是告诉您请求的状态。您应该检查status


如果必须使用同步请求,则完全不需要或不需要onreadystatechange处理程序。这是解决所有这些问题的版本:

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




出于完整性考虑:同步ajax请求使UX效果不佳,并且可能在某个时候完全淘汰。相反,请使用异步请求并让urlExists返回promise:

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访问的URL,因此通常仅源于同一来源的URL。如果那是您的用例,那很好,但是我想我会提到它。

09-17 01:14