简介 

  异步回调的书写往往打乱了正常流的书写方式,在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/Await可能最完整入门攻略

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

  2. 异步Promise及Async/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基础修炼(7)——Promise,异步,可靠性

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

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

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

  8. 异步编程之Generator(1)——领略魅力

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

  9. 4、promise

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

随机推荐

  1. @autowired和@resource的区别

    @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自 动注入罢了.@Resource有两个属性是比较重要的, ...

  2. GIT 版本控制常用命令学习汇总

    GIT 版本控制常用命令汇总 git version 查看当前git版本信息 git help 获取全部命令帮助信息 git help <command> 获取指定命令帮助信息 git c ...

  3. liunx常用的命令

    计算机网络的主要优点是能够实现资源和信息的共享,并且用户可以远程访问信息.Linux提供了一组强有力的网络命令来为用户服务,这些工具能够帮助用户登录到远程计算机上.传输文件和执行远程命令等. 本章介绍 ...

  4. myeclipse自动补全增强

    参考资料:http://blog.csdn.net/gaoying_blogs/article/details/43086287

  5. Reversing Linked List

    原题连接:https://www.patest.cn/contests/pat-a-practise/1074 题目: Given a constant K and a singly linked l ...

  6. apache rewrite_mod 经典疑问解答

    1.RewriteRule ^(com\/.*)$ index.php?do=$1 问:上面的规则匹配表达式 "^(.*)$" 匹配的内容是什么 答:匹配内容是URI站点目录:/d ...

  7. C# RabbitMq .net 使用

    本文转载来自 [http://www.cnblogs.com/yangecnu/p/Introduce-RabbitMQ.html]写的很详细. 文件安装包官方DEMO下载地址是:http://pan ...

  8. java学习笔记(1)

    最近开始学习java基本技术,在这里总结一下我学到的内容: 1.Java的基本历史 java起源于SUN公司的一个GREEN的项目,其原先目的是:为家用消费电子产品发送一个信息的分布式代码系统,通过发 ...

  9. ASP.NET Core中使用URL重写

    ASP.NET Core 1.1 Preview 1 中新增了 URL Rewriting middleware ,终于可以进行 URL 重写了,实际使用体验一下. 首先要将 ASP.NET Core ...

  10. 走向面试之数据库基础:一、你必知必会的SQL语句练习-Part 1

    本文是在Cat Qi的参考原帖的基础之上经本人一题一题练习后编辑而成,非原创,仅润色而已.另外,本文所列题目的解法并非只有一种,本文只是给出比较普通的一种而已,也希望各位园友能够自由发挥. 一.三点一 ...