看过的一些相关的技术文章
http://liubin.github.io/promises-book/
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise
Promise介绍
Promise介绍
以前写一些异步的东西,都使用回调函数来执行的,这样的写法让人看起来很不舒服
比如写一个隔几秒就执行的一个回调的东西,然后在回调的时候,开始下一个异步
setTimeout(function(){ console.log(11111) setTimeout(function(){ console.log(22222) setTimeout(function(){ console.log(33333) setTimeout(function(){ console.log(44444) setTimeout(function(){ console.log(55555) },5000) },4000) },3000) },2000) },1000)
这代码开起来维护起来都会很麻烦的,后来的后来,es6支持原生的Promise,jquery支持Deferred,Promise后,异步问题就容易多了
一个原生的Promise实现上面的代码
function setTime(t){ return new Promise(function(resolve,reject){ setTimeout(function(){ resolve(); },t) }); } setTime(1000) .then(function(){ console.log(11111) return setTime(1000); }) .then(function(){ console.log(22222) return setTime(2000); }) .then(function(){ console.log(33333) return setTime(3000); }) .then(function(){ console.log(44444) return setTime(4000); }) .then(function(){ console.log(55555) })
什么是Promise?
Promise是抽象异步处理对象以及对其进行各种操作的组件。 其详细内容在接下来我们还会进行介绍,Promise并不是从JavaScript中发祥的概念。
Promise最初被提出是在 E语言中, 它是基于并列/并行处理设计的一种编程语言。
Promise的基本用法
new Promise(function(resolve, reject) { ... })
参数
带有 resolve 、reject两个参数的函数对象。 第一个参数用在处理执行成功的场景,第二个参数则用在处理执行失败的场景。 一旦我们的操作完成即可调用这些函数。
resolve是实例化后Promise用then里面调用的函数
reject是实例化后Promise用catch里面调用的函数
实例化的Promise有3个状态 :等待(pending)、已完成(fulfilled)、已拒绝(rejected)
实例化的Promise的状态,只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
then和catch方法
then方法
then方法负责添加针对已完成的处理函数,同一个实例化后的Promise可以有多个then,then方法默认会返回当前的Promise,也可以自己重新实例化一个新的Promise
then方法对应实例化时候,function的resolve
catch方法
catch方法负责添加针对拒绝状态下处理函数,同一个实例化后的Promise可以有多个catch,catch方法默认会返回当前的Promise,也可以自己重新实例化一个新的Promise
catch方法对应实例化时候,function的resolve
一个例子
new Promise(function(resolve,rejected){ var img = new Image(); img.src="http://www.paipai.com/xx.jpg"; //这个会失败 //img.src="https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png" //这个会成功 img.onload = function(){ resolve(); } img.onerror = function(){ rejected(); } }) .then(function(){ console.log("图片加载成功!") }) .catch(function(){ console.log("图片加载失败!") })
all和race方法
all方法
Promise.all 接收一个 promise对象的数组作为参数,当这个数组里的所有promise对象全部变为resolve或reject状态的时候,它才会去调用 .then 方法
这个比较好用,当有多个请求的时候,一起请求,一起处理
return new Promise(function(resolve,rejected){ setTimeout(function(){ resolve(); },t) }) } Promise.all([setTime(1000),setTime(5000)]) .then(function(){ console.log("5秒后打印!"); })
race方法
只要有一个promise对象进入 FulFilled 或者 Rejected 状态的话,就会继续进行后面的处理。
function setTime(t){ return new Promise(function(resolve,rejected){ setTimeout(function(){ resolve(); },t) }) } Promise.race([setTime(1000),setTime(5000)]) .then(function(){ console.log("1秒后打印!"); })
一些用法的例子
Promise并非所有的浏览器都支持,比如ie就是不支持,幸好jquery也有类似的用法
1.一个异步里面接着另一个异步
原生Promise的实现
function setTime(t){ return new Promise(function(resolve,reject){ setTimeout(function(){ resolve(); },t) }); } setTime(1000) .then(function(){ console.log(11111) return setTime(1000); }) .then(function(){ console.log(22222) return setTime(2000); }) .then(function(){ console.log(33333) return setTime(3000); }) .then(function(){ console.log(44444) return setTime(4000); }) .then(function(){ console.log(55555) })
jquery的实现
function setTime(t){ return $.Deferred(function(dtd){ setTimeout(function(){ dtd.resolve(); },t); }); } setTime(2000) .then(function(){ console.log(11111) return setTime(1000); }) .then(function(){ console.log(22222) return setTime(2000); }) .then(function(){ console.log(33333) return setTime(3000); }) .then(function(){ console.log(44444) return setTime(4000); }) .then(function(){ console.log(55555) })
2.多个ajax串行的请求(满足后面的请求依赖前面的请求的情况)
原生的实现
chorme浏览器可以直接在博客园下的console直接运行,如果接口都还在的
var urls = { sideRight : "http://www.cnblogs.com/aggsite/SideRight", userStats : "http://www.cnblogs.com/aggsite/UserStats" } function get(URL){ return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function () { if (req.status === 200) { resolve(req.responseText); } else { reject(); } }; req.onerror = function () { reject(); }; req.send(); }); } get(urls.sideRight) .catch(function(){ console.log("请求失败!!!"); }) .then(function(html){ console.log(html); console.log("-----------------------------------------------------------") return get(urls.userStats); }) .catch(function(){ console.log("请求失败!!!"); }) .then(function(html){ console.log(html) })
jquery的实现
var urls = { sideRight : "http://www.cnblogs.com/aggsite/SideRight", userStats : "http://www.cnblogs.com/aggsite/UserStats" } $.ajax({ url : urls.sideRight, type : "get", dataType : "html" }) .fail(function(){ console.log("请求失败!!!"); }) .done(function(html){ console.log(html) console.log("-----------------------------------------------------------") return $.ajax({ url : urls.userStats, type : "get", dataType : "html" }); }) .fail(function(){ console.log("请求失败!!!"); }) .done(function(html){ console.log(html) })
3.多个请求并行发送(适用于多个请求才能渲染出一个页面的情况)
原生Promise实现
var urls = { sideRight : "http://www.cnblogs.com/aggsite/SideRight", userStats : "http://www.cnblogs.com/aggsite/UserStats" } function get(URL){ return new Promise(function (resolve, reject) { var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function () { if (req.status === 200) { resolve(req.responseText); } else { reject(URL); } }; req.onerror = function () { reject(URL); }; req.send(); }); } Promise.all([get(urls.sideRight),get(urls.userStats)]) .then(function(htmlArr){ console.log(htmlArr[0]) console.log("-----------------------------------------------------------") console.log(htmlArr[1]) }) .catch(function(url){ console.log(url+" : 失败了"); })
jquery实现
var urls = { sideRight : "http://www.cnblogs.com/aggsite/SideRight", userStats : "http://www.cnblogs.com/aggsite/UserStats1" } var $ajax1 = $.ajax({ url : urls.sideRight, type : "get", dataType : "html" }) var $ajax2 = $.ajax({ url : urls.userStats, type : "get", dataType : "html" }) $.when($ajax1,$ajax2) .done(function(response1Arr,response2Arr){ console.log(response1Arr[0]); console.log("----------------------------"); console.log(response2Arr[1]) }) .fail(function(res){ console.log("请求失败了") });
注:当任意一个请求失败的时候,都会进入fail