window 完全加载的 setTimeout 的最佳替代方法是什么?

What is the best replacement to setTimeout for window to be fully loaded?

J是一个具有各种功能的对象。

函数 u、t 和 z 应该是 运行,当 g、m 和 c 在 window 中完全加载时(对于网络和移动设备),这需要几毫秒供服务器响应。

替换 setTimeout 函数(800 毫秒)的最快或最佳方法是什么?

万分感谢,

J.o({p:'/dir/file-1.txt'});
J.e({
    g:'/dir/file-2.txt',
    m:'/dir/prefix-',
    c:'/dir/prefix-string.txt'
}); // a function that gets a few files with texts or JSON objects
setTimeout(function(){ 
    J.u({g: window['g'],m: window['m'],c: window['c']}); // a function to be run after loading three JSON objects in window
    J.t(window['p'],{t:"two"}); // a function to be run after loading another large JSON object
    J.z({});
}, 800);




// J.o function 
o:function(z){
    var g,h,x=[];

    Object.keys(z).forEach(function(a,b,c){
        window[a]=null;
        x[b]=new XMLHttpRequest();
        url=window.location.origin.concat('/',z[a.toString()]);
        x[b].open("GET",url,true);
        x[b].onreadystatechange=function (z){
            if(x[b].readyState===4){
                if(x[b].status===200 || x[b].status==0){
                    window[a]=x[b].responseText;
                }
            }
        }
        x[b].send();
     });
}



// J.e function for styles
e:function(z){
    var w,y,e,ar,x=[];
    Object.keys(z).forEach(function(a,b,c){
        window[a]=null;
        x[a]=new XMLHttpRequest();
        if(a=='m'){
            w=window.innerWidth; /*window size*/
            switch(true) {
                case(w<200):
                    window.y='a1';window.e=0.8; /*tiny*/ 
                    break;
                case(w>=200&&w<=360):
                    window.y='a2';window.e=0.9;/*x small*/
                    break;
                case(w>360&&w<=480):
                    window.y='a3';window.e=1; /*small*/
                    break;
                case(w>480&&w<=768):
                    window.y='a4';window.e=1.1; /*medium*/
                    break;
                case(w>768&&w<=1280):
                    window.y='a5';window.e=1.3; /*large*/
                    break;
                case(w>1280&&w<=1920):
                    window.y='a6';window.e=1.6; /*x large*/
                    break;
                case(w>1920):
                    window.y='a7';window.e=1.9; /*xx large*/
                    break;
                default:
                    window.y='a5';window.e=1.2; /*default size */
                    break;
            }
            url=window.location.origin.concat('/',z[a.toString()],window.y,'.txt');

        } else {
            url=window.location.origin.concat('/',z[a.toString()]);
        }
        x[a].open("GET",url,true);

        x[a].onreadystatechange=function (z){
            if(x[a].readyState===4){
                if(x[a].status===200 || x[a].status==0){
                    window[a]=x[a].responseText;
                }
            }
        }
        x[a].send();
     });
}

改为使用 Promises,然后您可以使用 Promise.all,它将在传递的数组中的所有 promise 都已解析时解析。不是 forEach 传递对象的 keys,而是 .map Promise 的每个键:

const getProm = (url) => new Promise((resolve, reject) => {
  const x = new XMLHttpRequest();
  x.open("GET", url, true);
  x.onreadystatechange = function() {
    if (x.readyState === 4) {
      if (x.status === 200 || x.status == 0) {
        resolve(x.responseText);
      } else {
        reject(x.status);
      }
    }
  }
});

// J.o function 
o: function(z) {
  var g, h, x = [];
  const proms = Object.keys(z).map(function(a, b, c) {
    window[a] = null;
    x[b] = new XMLHttpRequest();
    const url = window.location.origin.concat('/', z[a.toString()]);
    return getProm(url)
      .then((responseText) => {
        window[a] = responseText;
      });
  });
  return Promise.all(proms);
}

// J.e function for styles
e: function(z) {
  var w, y, e, ar, x = [];
  const proms = Object.keys(z).map(function(a, b, c) {
    window[a] = null;
    if (a == 'm') {
      w = window.innerWidth; /*window size*/
      switch (true) {
        case (w < 200):
          window.y = 'a1';
          window.e = 0.8; /*tiny*/
          break;
        case (w >= 200 && w <= 360):
          window.y = 'a2';
          window.e = 0.9; /*x small*/
          break;
        case (w > 360 && w <= 480):
          window.y = 'a3';
          window.e = 1; /*small*/
          break;
        case (w > 480 && w <= 768):
          window.y = 'a4';
          window.e = 1.1; /*medium*/
          break;
        case (w > 768 && w <= 1280):
          window.y = 'a5';
          window.e = 1.3; /*large*/
          break;
        case (w > 1280 && w <= 1920):
          window.y = 'a6';
          window.e = 1.6; /*x large*/
          break;
        case (w > 1920):
          window.y = 'a7';
          window.e = 1.9; /*xx large*/
          break;
        default:
          window.y = 'a5';
          window.e = 1.2; /*default size */
          break;
      }
      url = window.location.origin.concat('/', z[a.toString()], window.y, '.txt');

    } else {
      url = window.location.origin.concat('/', z[a.toString()]);
    }
    return getProm(url)
      .then((responseText) => {
        window[a] = responseText;
      });
  });
  return Promise.all(proms);
}

然后,您可以在 J.oJ.e 的调用中调用 Promise.all:

Promise.all([
  J.o({p:'/dir/file-1.txt'}),
  J.e({
    g:'/dir/file-2.txt',
    m:'/dir/prefix-',
    c:'/dir/prefix-string.txt'
  })
]).then(() => {
  console.log('All requests have finished');
})
.catch((e) => {
  // handle errors
});

请注意,如果您能设法切换到 fetch 而不是 XMLHttpRequest - fetch returns a Promise 会更优雅已经,所以没有必要用它显式构造一个 Promise:

const getProm = url => fetch(url).then((res => res.text());

但它在古老的浏览器中不受支持,因此要可靠地使用它,您还需要一个 polyfill。

如果您分配给 window[a] 的唯一原因是以后能够访问异步返回的值,请不要 - 相反,请使用 Promises 解析的值。例如:

Promise.all([
  getProm('foo'),
  getProm('bar')
])
.then(([foo, bar]) => {
  // foo and bar are variables which hold the response text for foo and bar
});

作为旁注,您可能会强烈考虑仅调试和更改 source 代码,而不是缩小的代码。精简代码读起来很痛苦。