异步Promise实现

时间:2023-02-21 16:02:53

简介 

  异步回调的书写往往打乱了正常流的书写方式,在ECMAScript 6中实现了标准的Promise API,旨在

解决控制回调流程的问题。

  简单的实现了Promise API: 

       (function(w){
function Promise(fn){
return this instanceof Promise ? this.init(fn) : new Promise(fn);
}
Promise.fulfill = function(m){return m;};
Promise.reject = function(m){throw m;};
Promise.map = {
resolve: "onFulfill",
reject: "onReject"
}
//异步自动生成promise并执行
Promise.resolve = function(fn){
var p = new Promise();
setTimeout(function(){
p.resolve();
},0);
if(fn)
p.callback["onFulfill"] = fn;
return p;
};
Promise.all = function(){
var p = new Promise(),
args;
var counter = 0,ret = [];//收集结果,并传给p
var v,fn; //传入的函数,执行该函数,将结果保存至ret
if(arguments.length > 1){
args = [].slice.apply(arguments)
}else if({}.toString.call(arguments[0]) == "[object Array]"){
args = arguments[0];
}
for(var i=0,len=args.length;i<len;i++){
if(typeof args[i] == "function"){
args[i] = Promise.resolve(args[i]);
} (function(i){
args[i].then(function(m){
ret.push(m);
if(--counter <= 0){
ret.length = len;
p.resolve(ret);
}
},function(){
p.reject();
});
})(i)
counter++;
}
return p;
};
Promise.prototype = {
init: function(fn){
var that = this;
this.state = 'pending';
this.callback = {
onFulfill: Promise.fulfill,
onReject: Promise.reject
};
this.dirty = false;
this._next = null;
setTimeout(function(){
fn && fn.call(that,that.resolve.bind(that),that.reject.bind(that));
},0) },
then: function(onFulfill,onReject){
return post.call(this,onFulfill,onReject);
},
wait: function(mills){ //promise链在wait处被分裂成2段
var p = new Promise(),
start = new Date().getTime();
var id = setTimeout(function(){ //传入时间
p.resolve([this.val,new Date().getTime() - start])
},mills);
p.cancel = function(){
clearTimeout(id);
}
return p;
}
}
function post(onFulfill,onReject,onNotify,onComplete){
var p = new Promise(),
that = this;
if(arguments.length <= 2){
that._next = p;
that.callback["onFulfill"] = onFulfill;
that.callback["onReject"] = onReject;
this.dirty = true;
}
return p;
}
function fire(promise,method){
var next = "resolve",val,
args = arguments[2];
if(promise.state == "pending"){
try{
promise.val = val = promise.callback[Promise.map[method]].apply(promise,args);
promise.state = method;
}catch(e){
promise.val = val = e;
next = "reject";
} if(val && isPromise(val)){
val._next = promise._next;
}else{
if(promise._next){
fire(promise._next,next,[val]);
}
} }
return promise;
}
function isPromise(o){
return o && typeof o == "object" && o.then && typeof o.then == "function";
}
"reject,resolve".replace(/\w+/g,function(m){
Promise.prototype[m] = function(){
return fire(this,m,arguments);
}
}) w.Promise = Promise;
})(window)

示例

  示例内容为依次加载网页内容的各个元素:先加载标题,并根据服务器返回的url信息,到相应的文件中加载

内容,并以此显示。

       var getJson = function(url){
return new Promise(function(resolve,reject){
var that = this;
var xhr = new XMLHttpRequest();
if(!window.Promise)return;
xhr.open('get',url);
xhr.onreadystatechange = function(e){
if(xhr.readyState == 4){
if(xhr.status >= 200 && xhr.status < 300 || xhr.status == 304){
resolve(xhr.responseText); log(that)
}else{
reject(new Error('response error'));
}
}
};
xhr.onerror = function(e){
reject(new Error('ajax error'));
}
xhr.send();
});
}; var body = document.body;
var addHtml = function(html){
if(typeof html != 'string') return;
var p = document.createElement('p');
p.textContent = html;
body.insertBefore(p,loading);
};
var addHead = function(html){
if(typeof html !== 'string') return;
var h = document.createElement('h2');
h.textContent = html;
body.insertBefore(h,loading);
}
var log = function(msg){console.log(msg)};
var loading = document.getElementById('loading'); getJson('../json/head.json').then(JSON.parse).then(function(html){
addHead(html.content);
Promise.all(html.urls.map(getJson)).then(function(arr){
arr.forEach(function(content){
addHtml(JSON.parse(content).content);
})
},function(e){
log('error in loading content: '+ e);
})
},function(e){
log('error: ' + e);
}).then(function(){
loading.style.display = 'none';
}) getJson('../json/head.json').then(JSON.parse).then(function(html){
addHead(html.content);
var promise = Promise.resolve();
html.urls.forEach(function(url,i){
promise = promise.then(function(){
return getJson(url);
}).then(JSON.parse).then(function(html){
addHtml(html.content);
},function(e){
log('error in loading body: '+ e );
}).then(function(){
if(i == html.urls.length-1)
loading.style.display = 'none';
})
})
})

示范

  Promise API控制流程,尤其是对于异步操作而言,流程非常清晰,开飞相对容易。

异步Promise实现的更多相关文章

  1. 异步Promise及Async&sol;Await可能最完整入门攻略

    此文只介绍Async/Await与Promise基础知识与实际用到注意的问题,将通过很多代码实例进行说明,两个实例代码是setDelay和setDelaySecond. tips:本文系原创转自我的博 ...

  2. 异步Promise及Async&sol;Await最完整入门攻略

    一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪圈, ...

  3. 异步-promise、async、await

    下面代码打印结果是? setTimeout(()=>{ console.log(1) }) new Promise((resolve,reject)=>{ console.log(2) r ...

  4. Promise与异步

    不知道promise,大家现在用了吗?如果还不了解的话,今天就来对了-基础的了解起来- 正文从这开始- 接触过promise的的都知道它的应用场景和用途,Promise可以用来避免异步操作函数里的嵌套 ...

  5. promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

    * promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...

  6. javascript基础修炼&lpar;7&rpar;——Promise,异步,可靠性

    开发者的javascript造诣取决于对[动态]和[异步]这两个词的理解水平. 一. 别人是开发者,你也是 Promise技术是[javascript异步编程]这个话题中非常重要的,它一度让我感到熟悉 ...

  7. Promise、async、await 异步解决方案

    参考: https://www.cnblogs.com/CandyManPing/p/9384104.html  或  https://www.jianshu.com/p/fe0159f8beb4(推 ...

  8. 异步编程之Generator&lpar;1&rpar;——领略魅力

    异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...

  9. 4、promise

    es5 中 var obj = { ajax: function (callback) { console.log('执行') setTimeout(function () { callback &a ...

随机推荐

  1. 【Star CCM&plus;实例】开发一个简单的计算流程&period;md

    流程开发在CAE过程中处于非常重要的地位. 主要的作用可能包括: 将一些经过验证的模型隐藏在流程中,提高仿真的可靠性 将流程封装成更友好的界面,降低软件的学习周期 流程开发实际上需要做非常多的工作,尤 ...

  2. C&num;数字格式化

    格式规范的完整形式:{index [,width][:formatstring]} index是此格式程序引用的格式字符串之后的参数,从零开始计数:width(可选) 是要设置格式的字段的宽度,wid ...

  3. treeiso

    主要包括了一些树同构的代码和一些树图生成器... download

  4. 快速熟悉Zbrush中的四种裁切笔刷

    ZBrush 4.0R4完善了裁切的功能.捷就可以把模型想要隐藏的地方用选择裁切的方法隐藏掉,其中ZBrush在®4.0R4软件中提供了4中裁切笔刷,分别为ClipCircle笔刷.ClipCircl ...

  5. STM32F407 外扩SRAM

    字节控制功能.支持高/低字节控制. 看看实现 IS62WV51216 的访问,需要对 FSMC进行哪些配置. 这里就做一个概括性的讲解.步骤如下: 1)使能 FSMC 时钟,并配置 FSMC 相关的  ...

  6. UILabel设置行间距和字间距并计算高度-b

    #define UILABEL_LINE_SPACE 6 #define HEIGHT [ [ UIScreen mainScreen ] bounds ].size.height //给UILabe ...

  7. sqoop使用的问题

    找不到表 17/05/02 18:15:47 ERROR tool.ImportTool: Imported Failed: There is no column found in the targe ...

  8. 【swoole】如何在docker&plus;swoole环境下测试udp服务

    前面几篇文章讲了使用 docker+swoole 环境来测试tcp服务以及如何测试,但是当我开始学习udp服务那块的时候,发现使用原来的方式在 docker+swoole 环境下行不通啦,后来发现如果 ...

  9. 《Linux性能及调优指南》1&period;3 Linux文件系统

    翻译:飞哥 (http://hi.baidu.com/imlidapeng) 版权所有,尊重他人劳动成果,转载时请注明作者和原始出处及本声明. 原文名称:<Linux Performance a ...

  10. 牛客网 Wannafly挑战赛12 删除子串&lpar;线性dp&rpar;

    题目描述 给你一个长度为n且由a和b组成的字符串,你可以删除其中任意的部分(可以不删),使得删除后的子串“变化”次数小于等于m次且最长. 变化:如果a[i]!=a[i+1]则为一次变化.(且新的字符串 ...