前端cdn选址

1、

2、

3、

4、

/***
 * 原生promise
 * @param promise2
 * @param x
 * @param resole
 * @param reject
 * @returns {*}
 */
function resolvePromise(promise2, x, resole, reject) {
  if (promise2 === x) {
    return reject(new Error("循环引用"));
  }
  if (typeof x === "function" || (typeof x === "object" && x !== null)) {
    var called;
    try {
      let then = x.then;
      if (typeof then === "function") {
        then.call(function (x, y) {
          if (called) return;
          called = true;
          resolvePromise(promise2, y, resole, reject);
        }, function (r) {
          if (called) return;
          called = true;
          reject(r);
        })
      } else {
        resole(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resole(x);
  }
}

function Promise(executor) {
  this.value  = "";
  this.reason = "";
  this.status = "pending";

  this.resolveCallbacks  = [];
  this.rejectedCallbacks = [];
  try {
    executor(this.resolve.bind(this), this.reject.bind(this))
  } catch (e) {
    this.reject.call(this, e);
  }
}

Promise.prototype.resolve = function (value) {
  if (this.status === "pending") {
    this.status = "fulfilled";
    this.value  = value;
    for (var i = 0; i < this.resolveCallbacks.length; i++) {
      this.resolveCallbacks[i]();
    }
  }
};
Promise.prototype.reject  = function (reason) {
  if (this.status === 'pending') {
    this.status = "rejected";
    this.reason = reason;
    for (var i = 0; i < this.rejectedCallbacks.length; i++) {
      this.rejectedCallbacks[i]();
    }
  }
};
Promise.prototype.then    = function (onfulfilled, onrejected) {
  var promise2, _this = this;

  promise2 = new Promise(function (resolve, reject) {
    if (_this.status === "fulfilled") {
      setTimeout(function () {
        try {
          var x = onfulfilled(_this.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }, 0);
    }

    if (_this.status === "rejected") {
      setTimeout(function () {
        try {
          let x = onrejected(_this.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }, 0);
    }

    if (_this.status === "pending") {
      _this.resolveCallbacks.push(function () {
        setTimeout(function () {
          try {
            let x = onfulfilled(_this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0)
      });

      _this.rejectedCallbacks.push(function () {
        setTimeout(function () {
          try {
            let x = onrejected(_this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      })


    }
  });
  return promise2;
};
Promise.prototype.catch   = function (rejectFuc) {
  return this.then(null, rejectFuc);
};
Promise.prototype.finally = function (callback) {
  this.then(callback, callback);
};
Promise.resolve           = function (value) {
  return new Promise(function (resolve, reject) {
    resolve(value);
  });
};
Promise.reject            = function (reason) {
  return new Promise(function (resolve, reject) {
    reject(reason);
  })
};
Promise.race              = function (values) {
  return new Promise(function (resolve, reject) {
    for (var i = 0; i < values.length; i++) {
      var current = values[i];
      if (typeof current === "function" || (typeof current === "object") && current !== null) {
        var then = current.then;
        if (typeof then === "function") {
          then.call(current, resolve, reject);
        } else {
          reject(current);
        }
      } else {
        resolve(current);
      }
    }
  })
};

/**
 * app相关函数
 * @param files
 */
function app(files) {
  app.files = files;
  //注入运维js到全局
  this.app.yunwei();
}

app.isFunction        = function (fn) {
  return Object.prototype.toString.call(fn) === '[object Function]';
};
//引入运维js
app.yunwei            = function () {
  this.create.inserted({
    css: [],
    js : ['./saconfig/secure/yunwei.js']
  }, 'head', this.cdnEntry);
};
//cdn入口文件
app.cdnEntry          = function () {
  var cdnServer = sessionStorage.getItem("cdnServer");
  if (cdnServer) {
    app.setCdnServer(cdnServer);
    return app.create.inserted(app.files);
  }
  //cdn 选址
  cdns = window.yunweiConfig.cdns, cdnList = [];
  if (cdns.length > 0) {
    for (var i = 0; i < cdns.length; i++) {
      cdnList.push({
        url   : cdns[i] + '/cdn/static/cdn_test.txt',
        origin: cdns[i]
      });
    }
    return this.app.cdnTest(cdnList).then(function (data) {
      app.setCdnServer(data.origin);
      //创建html标签
      app.create.inserted(app.files);
    }, function (err) {
      app.create.inserted(app.files);
    });
  }
  //没有配置cdn
  app.create.inserted(app.files);
};
//cdn选址
app.cdnTest           = function (cdn) {
  var ajax = [], cache = [], errs = [];
  for (var i = 0; i < cdn.length; i++) {
    ajax.push(function (index) {
      return new Promise(function (resolve, reject) {
        var xhr = new app.Ajax().fetch({
          url    : cdn[index].url,
          origin : cdn[index],
          success: function () {
            resolve(cdn[index]);
          },
          fail   : function (err) {
            errs.push(err);
            if (errs.length >= cdn.length) {
              reject(cdn[index])
            }
          }
        });
        cache.push(xhr)
      })
    }(i))
  }
  return new Promise(function (resolve, reject) {
    Promise.race(ajax).then(data => {
      app.Ajax().cancel(cache);
      resolve(data);
    }, function (err) {
      reject(err);
    });
  });
};
app.setCdnServer      = function (cdn) {
  yunweiConfig.cdnServer = cdn;
  sessionStorage.setItem("cdnServer", cdn);
};
app.getLocationOrigin = function () {
  return location.origin;
};
app.Ajax              = function (options) {
  var XHR    = function (options) {
    var params  = {
      methods: "GET",
      url    : "",
      timeout: 3000,
      success: undefined,
      err    : undefined,
    };
    params      = Object.assign(params, options);
    var xhrHttp = new XMLHttpRequest();
    xhrHttp.open(params.methods, params.url);
    xhrHttp.timeout = params.timeout;
    xhrHttp.send();
    xhrHttp.onreadystatechange = function () {
      if (xhrHttp.readyState === 4) {
        if (xhrHttp.status === 200) {
          if (app.isFunction(params.success)) {
            params.success(xhrHttp.responseText);
          }
        } else {
          if (app.isFunction(params.fail)) {
            params.fail(xhrHttp.responseText);
          }
        }
      }
    };
    xhrHttp.onerror            = function (e) {
      if (app.isFunction(params.fail)) {
        params.fail(e);
      }
    };
    xhrHttp.ontimeout          = function (e) {
      if (app.isFunction(params.fail)) {
        params.fail(e);
      }
    };
    return xhrHttp;
  };
  XHR.cancel = function (cache) {
    cache[0].abort();
    for (var c = 0; c < cache.length; c++) {
      var xhr = cache[c];
      xhr.abort();
    }
    return this;
  };
  return {
    fetch : XHR,
    cancel: XHR.cancel
  };

};
app.create            = {
  inserted        : function (assets, type, fn) {
    var tags = this.generateHtmlTags(assets);
    if (type === "head") {
      tags.head = tags.body;
      tags.body = [];
    }
    if (tags.head.length > 0) {
      this.createTag("head", tags.head, fn);
    }
    if (tags.body.length > 0) {
      this.createTag('body', tags.body, fn);
    }
  },
  generateHtmlTags: function (assets) {
    var js  = this.createJs(assets.js);
    var css = this.createCss(assets.css)
    return {
      head: css,
      body: js
    };
  },

  createJs : function (files) {
    var scripts = [];
    for (var i = 0; i < files.length; i++) {
      scripts.push({
        tagName   : 'script',
        closeTag  : true,
        attributes: {
          type: 'text/javascript',
          src : files[i]
        }
      });
    }
    return scripts
  },
  createCss: function (files) {
    var styles = [];
    for (var i = 0; i < files.length; i++) {
      styles.push({
        tagName   : 'link',
        attributes: {
          href: files[i],
          rel : 'stylesheet'
        }
      });
    }
    return styles
  },
  createTag: function (target, files, fn) {
    try {
      var parent = document[target];
      if (!files.length) return;
      var cdn = "";
      if (window.yunweiConfig) {
        cdn = window.yunweiConfig.cdnServer ? window.yunweiConfig.cdnServer : '';
      }
      for (var i = 0; i < files.length; i++) {
        this.insertDom(parent, cdn, files[i], i, fn);
      }

    } catch (e) {
      console.log(e)
    }

  },
  insertDom: function (parent, cdn, file, num, fn) {
    var time = new Date().getTime(), src;
    var tag  = document.createElement(file.tagName);
    tag.type = file.attributes.type;
    src      = cdn + file.attributes.src;
    if (app.isFunction(fn)) {
      src = cdn + src + '?time' + '=' + time;
    }
    tag.src     = src;
    var onErr   = new this.onErr(parent, tag, file);
    tag.onerror = onErr.resetCdn;
    tag.onload  = function (e) {
      if (app.isFunction(fn))
        fn('加载完成');
    };
    parent.append(tag);
  },
  onErr    : function (parent, tag, file) {
    this.resetCdn = function (e) {
      if (e.type === "error") {
        tag.remove();
        app.setCdnServer(app.getLocationOrigin());
        app.create.insertDom(parent, window.yunweiConfig.cdnServer, file)
      }
    };
  }
};

发布了80 篇原创文章 · 获赞 5 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_28473733/article/details/105457495
cdn