123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894 |
- var comm = {
- data: {
- baseUrl: ''
- },
- /* ====================================================================================== */
- addEvent: function (ele, ev, fn) { // 添加事件的函数
- //针对IE浏览器
- if (ele.attachEvent) {
- ele.attachEvent('on' + ev, fn)
- }
- //针对FF与chrome
- else {
- ele.addEventListener(ev, fn, false)
- }
- },
- ajax: function (options) { // 封装ajax
- var _this = this;
- //异步请求对象的完成状态
- this.done = 0;
- this.format = function () {
- var now = new String(new Date().getTime());
- return now.substr(0, now.length - 3);
- }
- //格式化参数
- this.formatParams = function (data) {
- //获取地址参数
- var arr = [];
- for (var name in data) {
- arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name]));
- }
- arr.push("t=" + _this.format());//按分钟刷一次
- return arr.join("&");
- }
- //传入设置
- options = options || {};
- //请求方式
- options.type = (options.type || "GET").toUpperCase();
- options.dataType = options.dataType || "json";
- options.async = options.async || true;
- options.contentType = options.contentType || 'application/x-www-form-urlencoded';
- var params = _this.formatParams(options.data);
- if (options.contentType == "application/json;charset=utf-8") {
- params = JSON.stringify(options.data)
- }
- //创建异步请求对象 - 第一步
- var xhr;
- //w3c标准
- if (window.XMLHttpRequest) {
- xhr = new XMLHttpRequest();
- }
- //兼容IE6及以下
- else if (window.ActiveObject) {
- xhr = new ActiveXObject('Microsoft.XMLHTTP');
- }
- //连接 和 发送 - 第二步
- //判断是那种类型的请求
- //若是get请求
- if (options.type == "GET") {
- //参数拼接
- if (options.url.indexOf("?") == -1) sp = "?"; else sp = "&";
- //发送请求
- xhr.open("GET", options.url + sp + params, options.async);
- xhr.send(null);
- }
- //若是post请求
- else if (options.type == "POST") {
- //发送请求
- xhr.open("POST", options.url, options.async);
- //设置表单提交时的内容类型
- xhr.setRequestHeader("Content-Type", options.contentType);
- //参数配置
- xhr.send(params);
- }
- //接收 - 第三步
- xhr.onreadystatechange = function () {
- if (xhr.readyState == 4) {
- //状态码
- var status = xhr.status;
- //状态码表示成功时,执行成功回调函数
- if (status >= 200 && status < 300 || status == 304) {
- //返回数据的格式
- //json字符串
- if (options.dataType == "json") {
- try {
- options.success && options.success(eval("(" + xhr.responseText + ")"));
- }
- catch (err) {
- options.success && options.success(JSON.parse(xhr.responseText), xhr.responseXML);
- }
- }
- //普通字符串
- else {
- options.success && options.success(xhr.responseText, xhr.responseXML);
- }
- // 改变状态为完成
- _this.done = 1;
- }
- //如果状态码表示失败时调用错误处理回调函数
- else {
- options.error && options.error(status);
- // 改变状态为完成
- _this.done = 1;
- }
- }
- }
- },
- /* ====================================================================================== */
- hasClass: function (ele, cls) { // 判断一个类是否存在
- return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
- },
- addClass: function (ele, cls) { // 增加一个类
- if (!this.hasClass(ele, cls)) ele.className = ele.className.replace(/(\s*$)/g, "") + " " + cls
- },
- removeClass: function (ele, cls) { // 删除一个类
- if (this.hasClass(ele, cls)) {
- var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
- ele.className = ele.className.replace(reg, ' ')
- }
- },
- getStyle: function (ele, attr) { // 获取某个元素的样式
- var res = '';
- if (window.getComputedStyle) {
- res = getComputedStyle(ele)[attr];
- } else if (ele.currentStyle) {
- res = ele.currentStyle[attr];
- } else {
- res = ele.style[attr];
- }
- // 这里返回的样式做了调整,返回必须为字符串,有盒子的样式获取像margin-left会返回纯数字(不含单位px),这样不好处理,统一变成字符串后再对返回结果用正则匹配
- return res + '';
- },
- /* ====================================================================================== */
- show: function (ele) { // 让一个元素隐藏(display)
- ele.style.display = 'block'
- },
- hide: function (ele) { // 让一个元素显示(display)
- ele.style.display = 'none'
- },
- isShow: function (ele) { // 判断某个元素的是否显示(display,浅)
- var getVisibility = ele.style.display;
- return getVisibility !== "none";
- },
- isShowDeel: function (ele) { // 判断某个元素是否显示(display,深)
- temp = ele
- var getVisibility = this.getStyle(temp, 'display');
- if (getVisibility == 'none') {
- return false;
- } else if (temp.tagName == 'BODY') {
- return true;
- } else {
- return this.isShowDeel(temp.parentNode);
- }
- },
- visible: function (ele) { // 让一个元素隐藏(visibility)
- ele.style.visibility = 'visible'
- },
- hidden: function (ele) { // 让一个元素显示(visibility)
- ele.style.visibility = 'hidden'
- },
- visibleClass: function (cls) { // 让一个类的元素隐藏(visibility)
- var arr = document.getElementsByClassName(cls)
- for (var i = 0; i < arr.length; i++) {
- arr[i].style.visibility = 'visible'
- }
- },
- hiddenClass: function (cls) { // 让一个类的元素显示(visibility)
- var arr = document.getElementsByClassName(cls)
- for (var i = 0; i < arr.length; i++) {
- arr[i].style.visibility = 'hidden'
- }
- },
- /* ====================================================================================== */
- addElement: function (ele, tag, cls, data, inner, fn) { // 为一个元素创建一个子元素
- // 1、创建新元素
- var newEle = document.createElement(tag)
- // 2、设置各种属性(图片地址,自定义属性等)
- newEle.setAttribute('class', cls);
- for (var item in data) {
- newEle.setAttribute(item, data[item]);
- }
- // 3、设置内容(innerhtml)
- newEle.innerHTML = inner ? inner : ''
- // 4、设置回调函数
- fn && fn(newEle)
- // 5、将新元素加入到父元素中
- ele.appendChild(newEle)
- },
- // 帧动画(定时器容器(存在一个对象内的一个属性),图片群所在的元素,执行速度(单位:毫秒),是否只执行一次,执行完毕的回调函数)
- zhenAnimation: function (interval, ele, speed, once, fn) {
- var cont = document.getElementsByClassName('container')[0]
- // 清除定时器
- clearInterval(cont[interval])
- // 获取图片群并全部隐藏
- var imgs = ele.getElementsByTagName('img')
- for (var i = 0; i < imgs.length; i++) {
- imgs[i].style.visibility = 'hidden'
- }
- // 单独显示第一张图
- var i = 0
- imgs[i].style.visibility = 'visible'
- // 设置定时器
- cont[interval] = setInterval(function() {
- // 判断是否只执行一次
- if (i == imgs.length-1 && once) {
- // 每轮执行完成的回调函数
- clearInterval(cont[interval])
- fn&&fn()
- return
- }
- // 前一张图隐藏、后一张图显现、可循环执行
- imgs[i++].style.visibility = 'hidden'
- if (i == imgs.length) {i=0; fn&&fn()}
- imgs[i].style.visibility = 'visible'
- }, speed)
- },
- // 帧动画加强版,ele格式:<div id="yw1" data-url="图片地址前缀(不包括编号.png)" data-max="个数(帧动画图片数量+1)">
- zhenAnimationPro: function (interval, ele, speed, once, fn) {
- // 判断是否第一次执行该帧动画,是则加载图片
- if (!ele.getAttribute('isload')) {
- var src = ele.getAttribute('data-url')
- for (var j = ele.getAttribute('data-max'); j >= 0; j--) {
- ele.innerHTML = '<img src="' + src + comm.addPreZero(j) + '.png" style="position: absolute;visibility: hidden;">' + ele.innerHTML
- }
- ele.setAttribute('isload', 1)
- }
- var cont = document.getElementsByClassName('container')[0]
- // 清除定时器
- clearInterval(cont[interval])
- // 获取图片群并全部隐藏
- var imgs = ele.getElementsByTagName('img')
- for (var i = 0; i < imgs.length; i++) {
- imgs[i].style.visibility = 'hidden'
- }
- // 单独显示第一张图
- var i = 0
- imgs[i].style.visibility = 'visible'
- // 设置定时器
- cont[interval] = setInterval(function() {
- // 判断是否只执行一次
- if (i == imgs.length-1 && once) {
- // 每轮执行完成的回调函数
- clearInterval(cont[interval])
- fn&&fn()
- return
- }
- // 前一张图隐藏、后一张图显现、可循环执行
- imgs[i++].style.visibility = 'hidden'
- if (i == imgs.length) {i=0; fn&&fn()}
- imgs[i].style.visibility = 'visible'
- }, speed)
- },
-
- /* ====================================================================================== */
- setCookie: function (name, value, t) { // 设置cookie
- var hour = t ? t : 8;
- var exp = new Date();
- exp.setTime(exp.getTime() + hour * 60 * 60 * 1000);
- document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString() + ";path=/";
- },
- getCookie: function (name) { // 获取cookie 存在返回值,不存在返回null
- var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
- if (arr = document.cookie.match(reg)) {
- if (arr[2] != "undefined")
- return unescape(arr[2]);
- else return undefined;
- } else {
- return null;
- }
- },
- /* ====================================================================================== */
- getQueryString: function (name) { // 获取url的某个参数
- var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
- var r = window.location.search.substr(1).match(reg);
- if (r != null && unescape(r[2]) != "undefined" && unescape(r[2]) != "null") return unescape(r[2]);
- return '';
- },
- urlParam: function (obj) { // 将对象转换为url参数字符串
- var _this = this;
- var arr = [];
- for (var name in obj) {
- arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(obj[name]));
- }
- return arr.join("&");
- },
- getRandom: function (min, max) { // 获取随机数
- return Math.floor(Math.random() * (max - min)) + min;
- },
- arrRandom: function (arr) { // 使数组随机排序,返回一个新数组
- arr.sort(function () {
- return 0.5 - Math.random()
- })
- },
- createArr: function (arr, num, content) { // 生成数组,
- // 调用举例:comm.createArr(arr, 'num', 'content')
- // 输出举例:var arr = [{num: 5, content: {id: 1, imgurl: 'img/1.jpg'}}, {num: 2, content: {id: 2, imgurl: 'img/2.jpg'}}]
- var newArr = []
- for (var i = 0; i < arr.length; i++) {
- for (var j = 0; j < arr[i][num]; j++) {
- newArr.push(arr[i][content])
- }
- }
- return newArr
- },
-
- /* ====================================================================================== */
- isPhone: function (phone) { // 判断是否为有效手机号
- if (!(/^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/.test(phone))) {
- return false;
- } else {
- return true
- }
- },
- timestamp: function (time) { // 转换时间格式过滤器
- var sec = Math.floor(time % 60)
- var min = Math.floor(time / 60 % 60)
- var hour = Math.floor(time / 60 / 60)
- sec = sec < 10 ? '0' + sec : sec
- min = min < 10 ? '0' + min : min
- hour = hour < 10 ? '0' + hour : hour
- var timeStr = hour + ':' + min + ':' + sec;
- return timeStr
- },
- addPreZero: function (num) { // 帧动画补零过滤器
- if (num < 10) {
- return '0000' + num;
- } else if (num < 100) {
- return '000' + num;
- } else if (num < 1000) {
- return '00' + num;
- } else if (num < 10000) {
- return '0' + num;
- } else {
- return num;
- }
- },
- /* ====================================================================================== */
- Debuglog: function (text) { // 弹窗,用于测试
- if (typeof printWind == "undefined") {
- window.printWind = document.createElement("div");
- window.inner = document.createElement("div");
- inner.style.width = "600px";
- inner.style.position = "absolute";
- inner.style.right = "0px";
- printWind.appendChild(inner);
- printWind.style.position = "fixed";
- printWind.style.right = "0";
- printWind.style.top = "0";
- printWind.style.background = "rgba(0,0,0,0.6)";
- printWind.style.zIndex = "99999";
- printWind.style.padding = "20px";
- printWind.style.fontSize = "20px";
- printWind.style.width = "600px";
- printWind.style.height = "600px";
- printWind.style.color = "#0aff08";
- document.body.appendChild(printWind);
- }
- var para = document.createElement("p"); //创建新的<p> 元素
- para.innerHTML = text;
- para.setAttribute("class", "newLine");
- para.style.padding = "5px";
- inner.appendChild(para);
- var a = inner.clientHeight - 600;
- inner.style.top = -a + "px";
- },
- tips: function (text, time) {
- time = time ? time : 1500;
- var para = document.createElement("div"); //创建新的<p> 元素
- para.innerHTML = text;
- para.style.zIndex = 10000;
- para.style.borderRadius = '9px'
- para.style.backgroundColor = '#287AFF'
- para.style.textAlign = 'center'
- para.style.color = '#FFF'
- para.style.position = 'absolute'
- para.style.fontSize = '20px'
- para.style.left = '450px'
- para.style.top = '250px'
- para.style.padding = '7px 27px'
- para.style.width = '380px'
- para.style.wordBreak = 'break-all'
- para.style.display = 'block'
- document.body.appendChild(para);
-
- setTimeout(function () {
- document.body.removeChild(para);
- }, time);
- },
- /* ====================================================================================== */
- STBUtil: {
- /**
- * 通过键值获取机顶盒对应信息
- * @param name [参数名] ex:UserToken--用户token,EPGDomain--EPG域名,areaid--地区编码,templateName--当前用户模板
- * @return []
- */
- getSTBKey: function (name) {
- var value = '';
- if (typeof (Authentication) === "object") {
- if (Authentication.CTCGetConfig) {
- value = Authentication.CTCGetConfig(name);
- } else if (Authentication.CUGetConfig) {
- value = Authentication.CUGetConfig(name);
- }
- }
- return value;
- },
- /**
- * 通过键值设置机顶盒对应信息
- * @param name [参数名]
- * @param value [参数值]
- */
- setSTBKey: function (name, value) {
- if (typeof (Authentication) === "object") {
- Authentication.CTCSetConfig(name, value);
- }
- },
- /**
- * 获取机顶盒 用户账号/业务账号
- * @return {string}
- */
- getSTBUserId: function () {
- var userId = '';
- try{
- if (typeof (Authentication) == 'object') {
- // 此方法经测试目前可以获取到华为,中兴,创维三款机顶盒型号
- userId = Authentication.CTCGetConfig('UserID');
- if (!userId){
- userId = Authentication.CUGetConfig("UserID");
- }
- //烽火的机顶盒
- if(!userId){
- userId =Authentication.CTCGetConfig("device.userid");
- }
- //中兴老的盒子获取机顶盒型号的方法
- if(!userId && typeof(ztebw) == 'object' ){
- stbModel = ztebw.ioctlRead("infoZTEHWType");
- if(!stbModel) {
- stbModel = ztebw.ioctlRead("infoHWProduct");
- }
- }
- }
- else{
- console.log("不支持Authentication!");
- }
- }
- catch(e){
- userId = '';
- }
- return userId;
- },
- /**
- * 获取机顶盒 设备ID
- * @return {string}
- */
- getSTBId: function () {
- var stbId = "";
- if (typeof (Authentication) == "object") {
- stbId = Authentication.CTCGetConfig("STBID");
- if (!stbId) {
- stbId = Authentication.CUGetConfig("STBID");
- }
- if (!stbId) {
- stbId = Authentication.CTCGetConfig("device.stbid"); // 烽火的机顶盒
- }
- }
- // 广西广电获取stbId
- if (!stbId && typeof (guangxi) === "object") {
- stbId = guangxi.getStbNum();
- }
- return stbId;
- },
- /**
- * 获取机顶盒型号
- * @return {string}
- */
- getSTBModel: function () {
- var stbModel = '';
- try{
- //此方法经测试目前可以获取到华为,中兴,创维三款机顶盒型号
- stbModel = Authentication.CTCGetConfig('STBType');
- if (!stbModel){
- stbModel = Authentication.CUGetConfig("STBType");
- }
- //烽火的机顶盒
- if(!stbModel){
- stbModel = Authentication.CTCGetConfig("device.stbmodel");
- }
- //中兴老的盒子获取机顶盒型号的方法
- if(!stbModel && typeof(ztebw) == 'object' ){
- stbModel = ztebw.ioctlRead("infoZTEHWType");
- if(!stbModel){
- stbModel = ztebw.ioctlRead("infoHWProduct");
- }
- }
- }
- catch(e){
- console.log("不支持获取机顶盒型号!");
- }
- return stbModel;
- },
- /**
- * 获取机顶盒mac地址
- * @return {string}
- */
- getSTBMac: function () {
- if (window.isWinOS) { //Windows操作系统
- return "00-00-00-00-00-00";
- }
- var mac = "";
- if (typeof (Authentication) == "object") {
- try {
- mac = Authentication.CUGetConfig("mac");
- if (!mac && typeof (ztebw) == "object") {
- var stbId = ztebw.ioctlRead("infoHWSN");
- mac = stbId.substring(stbId.length - 12);
- }
- if (!mac) {
- mac = Authentication.CTCGetLocalMAC();
- }
- } catch (e) { }
- }
- // 广西广电获取mac
- if (!mac && typeof iPanel === "object") {
- mac = iPanel.getGlobalVar("MAC_ETH0");
- }
- // 长虹机顶盒获取mac(四川广电)
- if (!mac && typeof (Ethernet) === "object") {
- mac = Ethernet.MACAddress;
- }
- if (mac) {
- while (mac.indexOf(":") !== -1) {
- mac = mac.replace(":", "");
- }
- } else {
- mac = "00-00-00-00-00-00";
- }
- return mac;
- },
- /**
- * 获取 EPG大厅地址
- * @return {string}
- */
- getEPGDomain: function () {
- var epgDomain = "";
- if (typeof (Authentication) == "object") {
- epgDomain = Authentication.CTCGetConfig("EPGDomain");
- if (!epgDomain) {
- epgDomain = Authentication.CUGetConfig("EPGDomain");
- }
- if (typeof epgDomain === "undefined" || epgDomain == null) {
- epgDomain = "";
- }
- }
- return epgDomain;
- },
- /**
- * 获取 UserToken
- * @return {string}
- */
- getUserToken: function () {
- var userToken = "";
- if (typeof (Authentication) == "object") {
- userToken = Authentication.CTCGetConfig("UserToken");
- if (!userToken) {
- userToken = Authentication.CUGetConfig("UserToken");
- }
- if (!userToken) {
- userToken = Authentication.CTCGetConfig("device.usertoken");
- }
- }
- return userToken;
- },
- }
- };
- // promise插件
- (function (window) {
- // 参考Joe-Xie:https://www.cnblogs.com/XieJunBao/p/9156134.html
- // 原生封装promise为了应对低版本浏览器不兼容问题
- // 异步串行思路:promise执行then是注册回调函数,then有多个就可以注册多个回调函数,但是若多个回调都是异步执行的,那我们要等上一个异步结束后才执行下一个异步,这是时候就需要上一个异步操作完成后,把这个完成状态告诉下一个回调,这样才可以异步串行。为了解决这个问题我们把异步完成状态托管给promise去管理
- // 流程:第一步注册:链式调用then函数,每执行一个then函数,返回一个桥梁promise(then函数中的成功回调和失败回调是写入这个promise的回调列表中的,注意成功回调的功能除了执行本身函数外还要更新下一个promise的状态)
- // 第二步执行:第一个promise的异步执行完,开始执行第一个promise的回调函数(回调函数又分两步走:第一步:resolvePromise解析回调返回值(如果是promise则说明是异步,就需要继续解析直到不是promise而是一个具体的值),第二步:当回调返回的值是一个具体值而不是promise时,调用第二个proomise的reslove方法将第二个proomise的状态更新为fulfilled,并将第一个promise的回调的值传入p2的回调函数中去执行)
- function MyPromise(fn) {
- var self = this;
- // 成功回调传的参数
- self.value = null;
- // 失败回调传的参数
- self.error = null;
- // 当前promise对象的状态
- self.status = "pending";
- // 存储成功回调列表
- self.onFulfilledCallbacks = [];
- // 存储失败回调列表
- self.onRejectedCallbacks = [];
- // 状态改变并执行回调
- // 成功
- function resolve(value) {
- // 判断传入参数是否由MyPromise构造的对象,若是,注册该函数
- if (value instanceof MyPromise) {
- return value.then(resolve, reject);
- }
- // 判断
- if (self.status === "pending") {
- setTimeout(function () {
- self.status = "fulfilled";
- self.value = value;
- // 执行成功回调
- // self.onFulfilledCallbacks.forEach(function(callback){callback(self.value)});
- // 向下兼容forEach
- for (var i = 0; i < self.onFulfilledCallbacks.length; i++) {
- self.onFulfilledCallbacks[i](self.value);
- }
- }, 0)
- }
- }
- // 失败
- function reject(error) {
- if (self.status === "pending") {
- setTimeout(function () {
- self.status = "rejected";
- self.error = error;
- // self.onRejectedCallbacks.forEach(function(callback){callback(self.error)});
- for (var i = 0; i < self.onRejectedCallbacks.length; i++) {
- self.onRejectedCallbacks[i](self.error);
- }
- }, 0)
- }
- }
- try {
- fn(resolve, reject);
- }
- catch (e) {
- reject(e);
- }
- }
- // 解析放回值
- // 用来解析回调函数的返回值x,x可能是普通值也可能是个promise对象
- // 因为回调函数既可能会返回一个异步的promise也可能会返回一个同步结果,所以我们把直接把回调函数的结果托管给bridgePromise,使用resolvePromise方法来解析回调函数的结果,如果回调函数返回一个promise并且状态还是pending,就在这个promise的then方法中继续解析这个promise reslove传过来的值,如果值还是pending状态的promise就继续解析,直到不是一个异步promise,而是一个正常值就使用bridgePromise的reslove方法将bridgePromise的状态改为fulfilled,并调用onFulfilledCallbacks回调数组中的方法,将该值传入,到此异步操作就衔接上了。
- function resolvePromise(bridgepromise, x, resolve, reject) {
- // bridgepromise是桥梁promise,x是桥梁promise中注册的成功回调的返回值,resolve和reject是桥梁promise的状态改变函数
- // 2.3.1规范,避免循环引用
- // 如果成功回调的值又是桥梁promise就返回循环传参的错误(死循环)
- if (bridgepromise === x) {
- return reject(new TypeError('Circular reference'));
- }
- var called = false;
- // // 如果x是一个promise,则通过递归
- // if (x instanceof MyPromise) {
- // //如果这个promise是pending状态,就在它的then方法里继续执行resolvePromise解析它的结果,直到返回值不是一个pending状态的promise为止(这里使用了递归的方法)
- // if (x.status === "pending") {
- // x.then(
- // function(y){
- // resolvePromise(bridgepromise, y, resolve, reject);
- // },
- // function(error){
- // reject(error);
- // }
- // );
- // }
- // else {
- // x.then(resolve, reject);
- // }
- // }
- // else
- // // 如果x是一个promise,则继续解析它的状态
- if (x != null && ((typeof x === 'object') || (typeof x === 'function'))) {
- try {
- var then = x.then;
- if (typeof then === 'function') {
- // then方法的指向传入的桥梁promise,也就是说该桥梁promise调用了then方法并传入了成功回调和失败回调
- then.call(
- x,
- // 传入then的成功回调
- function (y) {
- if (called) return;
- called = true;
- // 这里重新解析当前的桥梁promise,至于成功回调的返回值传空(这里目的是通过递归持续判断当前桥梁promise的状态)
- resolvePromise(bridgepromise, y, resolve, reject);
- },
- //传入then的失败回调
- function (error) {
- if (called) return;
- called = true;
- reject(error);
- }
- )
- }
- // 如果then不是一个函数,则以x为值改变promise状态并延长成功回调列表
- else {
- resolve(x);
- }
- }
- // 如果在取x.then值时抛出了异常,则以这个异常做为原因将promise拒绝。
- catch (e) {
- if (called) return;
- called = true;
- reject(e);
- }
- }
- // 如过x不是一个promise,则改变bridgePromise的状态改为fulfilled,并调用onFulfilledCallbacks回调数组中的方法,将该值传入
- else {
- resolve(x);
- }
- }
- // 注册回调函数
- MyPromise.prototype.then = function (onFulfilled, onRejected) {
- var self = this;
- // 搭建桥梁promise(即调用为then方法后重新返回一个新的promise对象)
- var bridgePromise;
- // 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
- onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (value) { return value };
- onRejected = typeof onRejected === "function" ? onRejected : function (error) { throw error };
- // 如果当前的promise对象是完成状态
- // 返回一个新的桥梁promise
- if (self.status === "fulfilled") {
- return bridgePromise = new MyPromise(function (resolve, reject) {
- setTimeout(function () {
- try {
- // 获取成功回调函数的返回值
- var x = onFulfilled(self.value);
- // 解析桥梁promise函数
- resolvePromise(bridgePromise, x, resolve, reject);
- }
- catch (e) {
- reject(e);
- }
- }, 0);
- })
- }
- // 如果当前的promise对象是拒绝状态
- if (self.status === "rejected") {
- return bridgePromise = new MyPromise(function (resolve, reject) {
- setTimeout(function () {
- try {
- var x = onRejected(self.error);
- resolvePromise(bridgePromise, x, resolve, reject);
- }
- catch (e) {
- reject(e);
- }
- }, 0);
- });
- }
- // 如果当前的promise对象是听候状态,则在当前promise对象的成功回调列表和失败回调列表中注入
- if (self.status === "pending") {
- return bridgePromise = new MyPromise(function (resolve, reject) {
- // 注意回调列表是把整个回调函数和回调解析函数一起注入的!!!!!,所以在执行回调时除运行回调函数还要,解析桥梁promise的状态(有可能桥梁promise中也有promise),解析中改变当前promise的状态,若当前promise的状态为完成状态才继续执行下一个注册好的回调
- self.onFulfilledCallbacks.push(function (value) {
- try {
- var x = onFulfilled(value);
- resolvePromise(bridgePromise, x, resolve, reject);
- }
- catch (e) {
- reject(e);
- }
- });
- self.onRejectedCallbacks.push(function (error) {
- try {
- var x = onRejected(error);
- resolvePromise(bridgePromise, x, resolve, reject);
- }
- catch (e) {
- reject(e);
- }
- });
- });
- }
- }
- MyPromise.prototype.MyCatch = function (onRejected) {
- return this.then(null, onRejected);
- }
- MyPromise.all = function (promises) {
- return new MyPromise(function (resolve, reject) {
- var result = [];
- var count = 0;
- for (var i = 0; i < promises.length; i++) {
- // (function(i){
- // return promises[i].then(function(data) {
- // result[i] = data;
- // if (++count == promises.length) {
- // resolve(result);
- // }
- // }, function(error) {
- // reject(error);
- // });
- // })(i)
- function closeTemp(i) {
- return promises[i].then(function (data) {
- result[i] = data;
- if (++count == promises.length) {
- resolve(result);
- }
- }, function (error) {
- reject(error);
- });
- }
- closeTemp(i)
- }
- });
- }
- MyPromise.race = function (promises) {
- return new MyPromise(function (resolve, reject) {
- for (var i = 0; i < promises.length; i++) {
- promises[i].then(function (data) {
- resolve(data);
- }, function (error) {
- reject(error);
- });
- }
- });
- }
- MyPromise.resolve = function (value) {
- return new MyPromise(function (resolve) {
- resolve(value);
- });
- }
- MyPromise.reject = function (error) {
- return new MyPromise(function (resolve, reject) {
- reject(error);
- });
- }
- MyPromise.promisify = function (fn) {
- return function () {
- var args = Array.from(arguments);
- return new MyPromise(function (resolve, reject) {
- fn.apply(null, args.concat(function (err) {
- err ? reject(err) : resolve(arguments[1])
- }));
- })
- }
- }
- window.MyPromise = MyPromise;
- })(window);
|