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到全局
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.bind(this));
};
//cdn入口文件
app.cdnEntry = function () {
var cdn = sessionStorage.getItem("cdn");
if (cdn) {
cdn = JSON.parse(cdn);
if ((this.getTime() - cdn.time) / 1000 < (window.yunweiConfig.cacheTime || 60)) {
this.setCdnServer(cdn.cdnServer,cdn.time);
return this.create.inserted(this.files);
}
}
//cdn 选址
cdns = window.yunweiConfig.cdns, cdnList = [];
if (cdns.length > 0) {
for (var i = 0; i < cdns.length; i++) {
cdnList.push({
url : cdns[i] + window.yunweiConfig.cdnPath+ '/cdn_test.txt',
origin: cdns[i]
});
}
return this.cdnTest(cdnList).then(function (data) {
this.setCdnServer(data.origin,this.getTime());
//创建html标签
this.create.inserted(this.files);
}.bind(this), function (err) {
this.setCdnServer(app.getLocationOrigin(),app.getTime());
this.create.inserted(this.files);
}.bind(this));
}
//没有配置cdn
this.setCdnServer(app.getLocationOrigin(),app.getTime());
this.create.inserted(this.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,time) {
yunweiConfig.cdnServer = cdn;
sessionStorage.setItem("cdn", JSON.stringify({
cdnServer:cdn,
time:time
}));
};
app.getTime = function () {
return new Date().getTime();
};
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 tag = document.createElement(file.tagName);
if(file.tagName === "script"){
var src;
tag.type = file.attributes.type;
src = cdn + file.attributes.src;
if (app.isFunction(fn)) {
src = cdn + src + '?time' + '=' + app.getTime();
}
tag.src = src;
}else {
tag.href = file.attributes.href;
href = cdn + file.attributes.href;
tag.href = href;
}
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.getTime());
if (file.tagName === "script") {
if (!app.create.recordErrNum[file.attributes.src]){
app.create.recordErrNum[file.attributes.src] = 1
}else {
app.create.recordErrNum[file.attributes.src] = app.create.recordErrNum[file.attributes.src] + 1;
}
if (app.create.recordErrNum[file.attributes.src] < 2) {
app.create.insertDom(parent, window.yunweiConfig.cdnServer, file);
}
}
if (file.tagName === "link") {
if (!app.create.recordErrNum[file.attributes.href]){
app.create.recordErrNum[file.attributes.href] = 1
}else {
app.create.recordErrNum[file.attributes.href] = app.create.recordErrNum[file.attributes.href] + 1;
}
if (app.create.recordErrNum[file.attributes.href] < 2) {
app.create.insertDom(parent, window.yunweiConfig.cdnServer, file);
}
}
}
};
},
recordErrNum: {}
};