Promise:一种解决回调问题的技术
首先我们要理解同步与异步的含义:
- 同步:函数在执行时会阻塞调用者,并在执行完毕后返回结果。
- 异步:函数在执行时不会阻塞调用者,但是一旦执行完毕就会返回结果。例如,处理Ajax请求时就是在处理异步调用。
简言之:
- 异步:操作之间没啥关系,同时进行多个操作
- 同步:同时只能做一件事
- 异步:代码更复杂
- 同步:代码简单
Promise —消除异步操作,本质上是一个状态机
- 当状态改变的时候,要调用之前挂起的then队列
- then的时候直接执行对应的函数,并且要给参数
- 用同步方式,书写异步代码
用法
let p = new Promise(function(resolve,reject){ //异步代码 //resolve --- 成功 //reject --- 失败 $.ajax({ url:'arr.txt', dataType:'json', success(arr){ resolve(arr); }, error(err){ reject(err); } }); }); //当有结果的时候就调用then p.then(function(arr){//相当于resolve alert(arr); },function(err){//相当于reject alert(err); });
用Promise创建一个getJSON
function getJSON(url) { return new Promise((resolve,reject)=>{ const request = new XMLHttpRequest();//创建一个XMLHttpRequest对象 request.open("GET",url);//初始化请求 request.onload = function() {//注册一个onload方法,当服务器响应后被钓鱼那个 try { if(this.status===200){ resolve(JSON.parse(this.response));//尝试解析字符串 }else { reject(this.status+" "+this.statusText); } }catch(e) { reject(e.message); } }; request.onerror = function() {//和服务器通信发生错误 reject(this.status+" "+this.statusText); }; request.send(); }) } //调用 function handle() { const result1 = getJSON('a.json'); result1.then(res=>{//回调成功返回 console.log(res); }).catch(e=>{//回调发生错误 console.log("Error:",e); }); } // Promise.all function handle() { const result1 = Promise.all([getJSON('a.json'), getJSON('b.json')]); result1.then(res=>{ console.log(res); //返回一个数组 }).catch(e=>{ }) } // Promise.race function handle() { const result1 = Promise.race([getJSON('a.json'), getJSON('c.json')]); result1.then(res=>{ console.log(res);//只会返回成功的第一个 }).catch(e=>{ }) } //Async async function handle() { try{ const result1 = await getJSON('./statics/json/a.json'); console.log(result1); }catch(e){ console.log(e); } } handle()
用Promise封装fetch,FormData数据流方式
let data = {data1:data1,data2:data2};//使用json格式 let p = postData(url,data); p.then(response=>{ //响应结果代码逻辑 }); function postData(url,data) { let formData = new FormData();//将json转换成FormData数据流 if(data instanceof Object){ for(let i in data){formData.append(i, data[i]);} } return new Promise(function(resolve,reject){ fetch(url,{ method: 'POST', mode: 'cors', credentials: 'include', body:formData }) .then(response => { return response.ok === true ? (response.json()) : reject({status:response.status}); }) .then(response => { resolve(response); }) .catch(err => { console.log(err); // reject({status:-1}); }) }) }
//基本使用 let p = new Promise(function(resolve,reject){ setTimeout(function(){ resolve(12); },500); }); p.then(function(num){ alert(num) },function(error){ alert(error); });
多个Promise
- Promise.all();
let p1 = new Promise(function(resolve,reject){ //异步代码 //resolve --- 成功 //reject --- 失败 $.ajax({ url:'arr.txt', dataType:'json', success(arr){ resolve(arr); }, error(err){ reject(err); } }); }); let p2 = new Promise(function(resolve,reject){ //异步代码 //resolve --- 成功 //reject --- 失败 $.ajax({ url:'json.txt', dataType:'json', success(arr){ resolve(arr); }, error(err){ reject(err); } }); }); //all(),Promise全都执行完之后 Promise.all([ p1,p2 ]).then(function(arr){ alert('全都成功'); let [res1,res2] = arr; alert(res1); },function(err){ alert('至少有一个失败') });
简化:不写两个Promise
function createPromise(url){ return new Promise(function(resolve,reject){ //异步代码 //resolve --- 成功 //reject --- 失败 $.ajax({ url:url, dataType:'json', success(arr){ resolve(arr); }, error(err){ reject(err); } }); }); } Promise.all([ createPromise('arr.txt'), createPromise('json.txt') ]).then(function(arr){ alert(’全都成功‘); let [res1,res2] = arr; alert(res1); },function(err){ alert(’至少有一个失败‘) });
结合jquery,高版本jquery自带Promise
Promise.all([ $.ajax({url:'arr.txt',dataType:'json'}), $.ajax({url:'json.txt',dataType:'json'}) ]).then(function(results){ let [arr,json] = result; },function(err){ });
其他用法
- Promise.race 竞争,
可以把它想象成赛马
,每个函数都是一匹马,最快的那匹马会取得胜利。
同时如5个资源,哪个先来,先用哪个
Promise.race([ $.ajax({url:'http://1.com'}), $.ajax({url:'http://2.com'}), $.ajax({url:'http://3.com'}), ])
Promise.all([ $.ajax({url:'arr.txt',dataType:'json'}), $.ajax({url:'json.txt',dataType:'json'}) $.ajax({url:'num.txt',dataType:'json'}), ]).then(results=>{ let [arr,json,num] = results; },err=>{ console.log(err); })
自个写一个Promise
class Promise { constructor(fn){ //重点 const _this = this; this.__queue = []; this.__succ_res = null; this.__erro_res = null; this.status=''; fn(function(...arg){ _this.__succ_res = arg; _this.status = 'succ'; _this.__queue.forEach(json=>{ json.fn1(...arg) }); },function(...arg){ _this.__erro_res = arg; _this.status='error'; }); } then(fn1,fn2){ if(this.status == 'succ'){ fn1(...this.__succ_res) }else if(this.status=='error'){ fn2(...this.__erro_res) }else { this.__queue.push({fn1,fn2}) } } all(arr) { let aResult= []; return new Promise(function(resolve,rject){ let i =0; next(); function next(){ arr[i].then(function(res){ aResult.push(res); i++; if(i==arr.length){ resolve(aResult); }else { next(); } },reject); } }) } }