异步Promise实现
简介
异步回调的书写往往打乱了正常流的书写方式,在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实现的更多相关文章
- 异步Promise及Async/Await可能最完整入门攻略
此文只介绍Async/Await与Promise基础知识与实际用到注意的问题,将通过很多代码实例进行说明,两个实例代码是setDelay和setDelaySecond. tips:本文系原创转自我的博 ...
- 异步Promise及Async/Await最完整入门攻略
一.为什么有Async/Await? 我们都知道已经有了Promise的解决方案了,为什么还要ES7提出新的Async/Await标准呢? 答案其实也显而易见:Promise虽然跳出了异步嵌套的怪圈, ...
- 异步-promise、async、await
下面代码打印结果是? setTimeout(()=>{ console.log(1) }) new Promise((resolve,reject)=>{ console.log(2) r ...
- Promise与异步
不知道promise,大家现在用了吗?如果还不了解的话,今天就来对了-基础的了解起来- 正文从这开始- 接触过promise的的都知道它的应用场景和用途,Promise可以用来避免异步操作函数里的嵌套 ...
- promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解
* promise承诺 * 解决js中异步编程的问题 * * 异步-同步 * 阻塞-无阻塞 * * 同步和异步的区别? 异步;同步 指的是被请求者 解析:被请求者(该事情的处理者)在处理完事情的时候的 ...
- javascript基础修炼(7)——Promise,异步,可靠性
开发者的javascript造诣取决于对[动态]和[异步]这两个词的理解水平. 一. 别人是开发者,你也是 Promise技术是[javascript异步编程]这个话题中非常重要的,它一度让我感到熟悉 ...
- Promise、async、await 异步解决方案
参考: https://www.cnblogs.com/CandyManPing/p/9384104.html 或 https://www.jianshu.com/p/fe0159f8beb4(推 ...
- 异步编程之Generator(1)——领略魅力
异步编程系列教程: (翻译)异步编程之Promise(1)--初见魅力 异步编程之Promise(2):探究原理 异步编程之Promise(3):拓展进阶 异步编程之Generator(1)--领略魅 ...
- 4、promise
es5 中 var obj = { ajax: function (callback) { console.log('执行') setTimeout(function () { callback &a ...
随机推荐
- 利用闭包实现多次ajax请求只执行最后一次
点一个按钮,则向服务器请求资源,不作处理时,多次点击后会有很多个请求在等待.我们知道一般我们用ajax是异步请求,那么我们快速重复点击一个按钮得到的结果其实我们并不知道是哪次点击的结果可能是第一次可能 ...
- CharSequence cannot be resolved. It is indirectly referenced from required .class files
最近在写项目的时候发现会莫名其妙的出现这个编译错误,网上查了下发现自己安装的是JDK1.8造成的 原因:JDK1.8版本现在还不稳定 解决方法:卸载JDK1.8,安装JDK1.7 扩展:发现安装JDK ...
- 平凡的KTV后台,不平凡的KTV数据
之前就是说过“一个项目有很多重要的步骤以及功能”,那我们现在就来看看对于KTV项目来说:后台是处于什么样的重要作用! 首先就得了解KTV后台的一些功能了: 1.歌曲管理 .歌手管理 .设置资源路径 2 ...
- 书中的银行,我们一起奋斗的C#,只因乐在其中~
梦回C#,只因心中还留有那么一点执着,相信大家应该也有这些感触吧!!所以呢?我想给大伙分享我的一些学习,也希望大家能给我多点建议,让我们一起进步,共同成长!!! 那么我们就来看一下该怎么运 ...
- canvas :曲线的面积图 加渐变效果
document.body.innerHTML = '<canvas></canvas>' var cvs = document.querySelector("can ...
- JQuery 获取父级元素、同级元素、子元素等
例: <div> <div id="div_1">这是内容1</div> <div id="div_2">这是内 ...
- JQM (功能栏、导航条)
在Mobile中导航条的基本结构: <div data-role="navbar"> ul>li>a </div> 其中含有“行(grid)”和 ...
- 利用SSH Filesystem实现远程文件系统
远程文件系统的访问有很多种不同的实现方式,一些常见的连接方式比其它特定情况下的更有用.最著名的一个例子就是微软的通用互联网文件系统(CIFS),它可以容许微软Windows"映射网 ...
- 从“差不多了”到 正式发布 -- 新浪微博WinPhone UWP版诞生记
本文粗略记述了UWP团队从接手新浪微博项目到发布第一版的过程.本文不是技术贴,而是回顾“软件工程周期失控是一种怎样的体验”. 接手新项目:捡了个大便宜 2016年1月份,UWP team开始接手新浪微 ...
- ASP.Net开发基础温故知新学习笔记
申明:本文是学习2014版ASP.Net视频教程的学习笔记,仅供本人复习之用,也没有发布到博客园首页. 一.一般处理程序基础 (1)表单提交注意点: ①GET通过URL,POST通过报文体: ②需在H ...