1. 首页
  2. web前端

深入解析ES6中的promise

深入解析ES6中的promise

作者 | Jeskson
来源 | 达达前端小酒馆

什么是Promise

Promise对象是用于表示一个异步操作的最终状态(完成或失败)以及其返回的值。

什么是同步,异步

同步任务会阻塞程序的执行,如alert,for

异步任务不会阻塞程序的执行,如setTimeou

使用Promise,then,catch,finally

Promise.all 和 Promise.race

Promise.resolve 和 Promise.reject

回调与Promise

回调函数,用于请求数据

function backFunction(fn) {  setTimeout(function() {   fn && fn();  }, 1000); }  // 调用 backFunction(function() {  console.log(1); // 1  backFunction(function() {   console.log(2); // 2    backFunction(function() {     console.log(3); // 3    });  }); });

Promise

function d() {  return new Promise(resolve = {   setTimeout(function() {    resolve(); // resolve成功的时候要做的事情   },1000);   // 1秒后调用resolve(),它是一个函数  }) }  d()  .then(function() {   console.log(1);   return d(); // Promise实例  })  .then(function() {   console.log(2);   return d(); // Promise实例  }).then(function() {   console.log(3);  });

对比回调

// 动画 function moveTo(el, x, y, fn) {  el.style.transform = `translate(${x}px, ${y}px)`;  setTimeout(function() {   fn && fn();  },1000); }  let el = document.querySelector('div');  document.querySelector('button').addeventListener('click', e  moveTo(el, 100, 100, function() {   console.log(1);   moveTo(el, 200, 200, function() {    console.log(2);   });  }) });
// promise function moveTo(el,x,y) {  return new Promise(resolve => {   el.style.transform = `translate(${x}px, ${y}px)`;   setTimeout(function() {    resolve();   },1000);  }); }  document.querySelector('button').addEventListener('click', e=>{  moveTo(el,100,100)   .then(function() {    console.log('da');    return moveTo(el, 200, 200);   })   .then(function() {     console.log('da2');   }).then(function() {     console.log('da2');   }); });

信任问题

// 使用第三方库 回调 function method(fn) {  // 回调  setTimeout(function() {   // 回调   fn && fn();   // 有可以有bug,被多调用一次   fn && fn();  },1000); }  // promise一旦被调用,成功或者是失败后,就不能再被修改  function method() {  return new Promise(resolve => {   setTimeout(function() {    //成功    resolve();    // 再调用就不会执行    resolve();   },1000);  }); }
// 控制反转  function method(fn) {  setTimeout(function() {   // 执行回调   fn && fn.call({a:1, b:2)};   // 改变指向  },1000); }  function method(fn) {  return new Promise(resolve => {   setTimeout(() => {    resolve();   },1000);  }); }

错误处理

then(resolve, reject)
then方法中的第二个回调,是失败的时候要做的事情

catch
使用实例的then方法,可以捕获错误

finally
不论成功与否,finally中的内容一定会执行

function fn(val) {  return new Promise((resolve, reject) => {   if(val) {    resolve(); // 成功的时候   } else {    reject(); // 失败的时候   }  }); }
fn(false)  .then( () => {   console.log("成功");  }, () => {   console.log("失败");  })  function fn(val) {  return new Promise((resolve, reject) => {   if(val) {    resolve(); // 成功的时候   } else {    reject('404'); // 失败的时候   }  }); }  fn(false)  .then( () => {   console.log("成功");  }, e => {   console.log(e);  })   promise 中resolve只能传递一个参数,如下:    function fn(val) {  return new Promise((resolve, reject) => {   if(val) {    resolve({name: 'da'}); // 成功的时候   } else {    reject('404'); // 失败的时候   }  }); }  fn(true)  .then( dada => {   console.log(data);  }, e => {   console.log(e);  })

catch会捕获错误,如果在回调中没有对错误进行处理

fn(true)  .then(data => {   console.log(data);   return fn(false);  })  .then( () => {   console.log('da'); // 不会执行,没处理错误  })  .then( () => {     })  .catch(e => {   console.log(e);   return fn(false);  }); // 直接输出到这    不能保证catch被执行

如果没有对失败做出处理,会报错

fn(true)   .then(data => {   console.log(data);   return fn(false);  })  .catch(e=> {   // 捕获错误   console.log(e);   return fn(false);  })  .finally( () => {   console.log(100);  });

Promise的三种状态

pending为进行中的状态,fulfilled为成功的状态,rejected为失败的状态。状态的改变时不可返的,一旦决议就不能修改(决议,状态的改变为决议),状态只能从pending到fulfilled,或者,从pending到rejected。

Promise.all方法可以把多个promise的实例包装成一个新的promise实例

Promise.all( [promise1, promise2] ) : Promise  数组中,如果promise都为true,则返回为true,决议为成功 如果数组中有一个为promise,那么返回的是false,决议为失败  如果是一个空数组,那么返回为true,决议为成功

模式多个请求的数据

function getData1() {  return new Promise((resolve, reject) => {   setTimeout( () => {    console.log('第一条数据加载成功');    resolve('data1');   },1000);  }); }  function getData2() {  return new Promise((resolve, reject) => {   setTimeout( () => {    console.log('第二条数据加载成功');    resolve('data2');   },1000);  }); }  function getData3() {  return new Promise((resolve, reject) => {   setTimeout( () => {    console.log('第三条数据加载成功');    resolve('data3'); // 改为 reject('err')   },1000);  }); }
let p = Promise.all( [getData1(), getData2(), getData3()] );  p.then(arr => {  console.log(arr); });  // 失败  p.then(arr => {  console.log(arr); }, e => {  console.log(e); });  let p = Promise.all([]); // 决议为成功  p.then( () => {  console.log(`da`); }, e => {  console.log(e); });
第一条数据加载成功 第二条数据加载成功 第三条数据加载成功

不用Promise.all

let count = 0; function getData1() {  setTimeout( () => {   console.log('第一条数据加载成功');   count ++;   func();   },1000); }  function getData2() {  setTimeout( () => {   console.log('第二条数据加载成功');   count ++;   func();   },1000); }  function getData3() {  setTimeout( () => {   console.log('第三条数据加载成功');   count ++;   func();   },1000); }  function getData4() {  setTimeout( () => {   console.log('第四条数据加载成功');   count ++;   func();   },1000); }  // 写一个方法: function func() {  if(count < 4)return;  console.log('全部拿到了'); }

调用

getData2(); getData3(); getData4();

深入解析ES6中的promise

let err = false; function getData1() {  setTimeout( () => {   console.log('第一条数据加载成功');   if(status) err = true;   count ++;   func();   },1000); }  function func() {  if(count < 4)return;  console.log('全部拿到了');   if(err) {   // ...  } }

Promise.race()

Promise.race([promise1, promise2]) : Promise
let p = Promise.race([getData1(), getData2(),getData3()]);  p.then (data=>{  console.log(data); })
let flag = false; function func(data) {  if(flag) return  flag = true;  console.log(data); }  function getData1() {  setTimeout(()=>{   console.log("第一条数据加载成功");   func({name: 'da'});  },500); }  function getData2() {  setTimeout( () => {   console.log("第二条数据加载成功");   func({name: 'dada'});  }, 1000); }  getData1(); getData2();  第一条数据加载成功 {name: 'da'} 第二条数据加载成功

Promise.resolve与Promise.reject

Promise.resolve() 与 Promise.reject()

// Promise.resolve 传递一个普通的值 let p1 = new Promise(resolve => {  resolve('成功!'); });  let p2 = Promise.resolve('成功!');  // 传递一个promise实例 let pro = new Promise(resolve => {  resolve('da'); });  let p = Promise.resolve(pro);  p.then(data => void console.log(data));
let obj = {  then (cb) {   console.log('da');   da('dada');  },  method() {   console.log('coding');  } }  // 立即执行 Promise.resolve(obj).then(data => {  console.log(data); });

Promise异步:

console.log(1);  let p = new Promise(resolve => {  console.log(2);  resolve();  console.log(3); });  console.log(4);  p.then(()=>{  console.log(5); });  console.log(6);  // 123465 

Promise改善了传统回调造成的代码难维护,控制反转等问题,promise是异步的,如果all接收的是空数组,马上会被决议为成功,如果race接受的是空数组,那么会被永远挂起,无限捕获错误问题。

resove和reject方法:

如果接收的是普通的值,那么就会立即决议为成功,并填充这个值,如果接收的是一个promise实例,那么返回这个promise实例,如果接收的是个thenable对象,则会把它包装成promise对象,并立即执行这个对象的then方法,reject会产生一个决议失败的promise并直接传递值。

JavaScript/ES6 Promise

JavaScript的Promise代表一个操作的结果还没有结果,就是如网络请求操作,当我们从某个数据源获取数据的时候,没有办法确定它什么时候能够返回,接受到响应。

Promise提供标准

doSomething()  .then(doSomethingElse)  .catch(handleError)  .then(doMore)  .then(doFinally)  .catch(handleAnotherError)

创建Promise

一个Promise使用Promise构造器创建,接受两个参数resolve,reject

 var promise = new Promise( function(resolve, reject) {  // new Promise resolve() reject() } 
XMLHttpRequest的promise版本:  function get(url) {  return new Promise(function(resolve, reject) {   var req = new XMLHttpRequest();   req.open('GET', url);   req.onload = function() {    if(req.status == 200) {     resolve(req.response);    }else{     reject(Error(req.statusText));    }   };   req.onerror = function() {    reject(Error("Network Error"));   };    req.send();   });  }

使用Promise

get(url)  .then(function(response) {  },function(err) {  })

处理错误:

get(url)  .then(function(response){  }, undefined)  .then(undefined, function(err){  })
get(url)  .then(function(response){  })  .catch(function(err){  })

链式

get(url)  .then(function(response){   response = JSON.parse(response);   var secondURL = response.data.url   return get(secondURL);  })  .then(function(response){   response = JSON.parse(response);   var thirdURL = response.data.url   return get(thirdURL);  })  .catch(function(err){   handleError(err);  });

并行执行Promise

Promise.all()方法每个promise数组成为则决议为成功,如果数组中有任意一个promise为失败则决议为失败。

任务一,任务二,任务三,.then() -> success 任务成功

ES6

Promise对象用于表示一个异步操作的最终状态,以及其返回的值。

语法:

new Promise(function (resolve, reject) { });

几种状态:

pending初始状态,既不是成功,也不是失败状态;fulfilled意味着操作成功完成;rejected意味着操作失败。

pending状态的Promise对象可能会触发filfilled状态,并传递一个值给响应的状态处理方法,也可能触发失败状态rejected并传递失败信息。

Promise.all(iterable)

这个方法返回一个新的promise对象,该promise对象在itearable参数中,当里面所有的的promise对象决议成功的时候才触发成功,否则里面如何一个promise对象决议失败的时候,立即触发promise对象的失败。

Promise.all方法常用于处理多个promise对象的状态集合。

Promise.race(iterable)

当iterable参数里的任意一个子promise被决议成功或者是决议失败后,父promise会用子promise的成功返回值,或是失败返回。

Promise.reject(reason)

返回一个状态为失败的promise对象,将给定的失败信息传递给对应的处理方法。

Promise.resolve(value)

返回一个状态为失败的promise对象,将给定的失败信息传递给对应的处理方法。

const myPromise = new Promise( (resolve, reject) => {  resolve('resolve'); // filfilled  reject('reject'); // rejected });
function myFunction(url) {  return new Promise( (resolve, reject) => {   xhr.open ("GET", url);   xhr.onload = () => resolve(xhr.responseText);   xhr.onerror = () => reject(xhr.statusText);   xhr.send();  }); };

当异步代码执行成功的时候,会调用resolve(),当异步代码执行失败的时候,会调用reject()。

模拟异步代码:

setTimeout(function(){  resolve('成功'); },250); });  myPromise.then(function(successMsg){ });

ES6 Promise对象

Promise对象是异步编程的一种解决方案,语法上,Promise是一个对象,从它那可以获取异步操作的信息。

Promise的状态,promise异步操作有三种状态,pending(进行中),fulfilled(已成功),reject(已失败)。除了异步操作的结果,任何其他操作都是无法改变这个状态。

const p1 = new Promise(function(resolve,reject){     resolve('success1');     resolve('success2'); });   const p2 = new Promise(function(resolve,reject){       resolve('success3');      reject('reject'); });  p1.then(function(value){       console.log(value); // success1 });  p2.then(function(value){      console.log(value); // success3 });

缺点,一旦建立Promise就会立即执行,无法中途取消,如果不设置回调函数,Promise内部会抛出错误,不会反应到外部。

then方法,接收两个函数作为参数。

第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。

const p = new Promise(function(resolve,reject){   resolve('success'); });   p.then(function(value){   console.log(value); });   console.log('first'); // first // success
const p = new Promise(function(resolve,reject){   resolve(1); }).then(function(value){ // 第一个then // 1   console.log(value);   return value * 2; }).then(function(value){ // 第二个then // 2   console.log(value); }).then(function(value){ // 第三个then // undefined   console.log(value);   return Promise.resolve('resolve');  }).then(function(value){ // 第四个then // resolve   console.log(value);   return Promise.reject('reject');  }).then(function(value){ // 第五个then //reject:reject   console.log('resolve:' + value); }, function(err) {   console.log('reject:' + err); }); 

then方法将返回一个resolved或是rejected状态的Promise对象用于链式调用。

热Promise

在JavaScript中,所有代码都是单线程的,也就是同步执行的,promise就是为了提供一个解决方案的异步编程。

promise的特点:只有异步操作可以决定当前处于的状态,并且任何其他操作无法改变这个状态;一旦状态改变,就不会在变。

状态改变的过程:从pending变为fulfilled和从pending变为rejected,状态改变后,就不会在改变了,这就叫已定型resolved

用法:

Promise对象是由关键字new及其构造函数来创建的。

 const promise = new Promise((resolve, reject) => {     // do something here ...     if (success) {         resolve(value); // fulfilled     } else {         reject(error); // rejected     } }); 

函数接收两个函数作为参数,分别是resolve和reject,当异步操作执行成功后,会将异步操作的结果作为参数传入resolve函数并执行,此时的状态由Promise状态从pending变为fulfilled;而失败会将异步操作的错误作为参数传入reject函数并执行,此时Promise对象状态从pending变为rejected。

通过then方法,将指定resolved状态和rejected状态的回调函数。

  promise.then(function(value) {       // success   }, function(error) {       // failure   });

Promise.all(iterable),iterable必须是一个可以迭代的对象,如Array

返回值为一个新的Promise实例。

var p1 = new Promise((resolve, reject) => {    setTimeout(resolve, 1000, 'one');  });  var p2 = new Promise((resolve, reject) => {    setTimeout(resolve, 2000, 'two');  }); var p3 = new Promise((resolve, reject) => {   setTimeout(resolve, 3000, 'three'); }); var p4 = new Promise((resolve, reject) => {   reject('p4 reject!'); }); var p5 = new Promise((resolve, reject) => {   reject('p5 reject!'); });  Promise.all([p1, p2, p3, p4, p5]).then(values => {    console.log(values); }, reason => {   console.log(reason) });  // p4 reject!

Promise.race(iterable),同理,返回值为一个新的Promise实例。

返回的新实例状态,会是最先改变状态的那个实例,如果不是Promise实例,先用Promise.resolve方法,如果传入的迭代为空,则返回的Promise永久等待。

一个Promise实例
原封不动的返回该实例;

var original = Promise.resolve('第二行');  var da = Promise.resolve(original);  da.then(function(value) {   console.log('value: ' + value); });  console.log('original === da ? ' + (original === da));  // "original === da ? true" // "value: 第二行"

跟随这个thenable对象的,采用它的最终状态;

let thenable = {   then: function(resolve, reject) {     resolve(41);   } }  let p = Promise.resolve(thenable);  p.then(function(value) {   console.log(value); })   // 41

直接将传入参数当最终结果,并返回一个新的Promise;

let p = Promsie.resolve(12);  p.then(function(number) {   console.log(number); })  // 12

直接返回一个resolved状态的Promise对象

let p = Promsie.resovle();  p.then(function() {   // do something  })

Promise.prototype.then()

p.then(onResolve, onReject);  p.then(function(value) {   }, function(reason) { });

Promise.prototype. catch()

p.catch(onReject)   p.catch(function(reason) {  });
   // bad promise   .then(function(data) {     // success   }, function(err) {     // error   });  // good promise   .then(function(data) {      // success   })   .catch(function(err) {     // error   });

Promise.prototype. finally()

  p.finally(onFinally);    p.finally(function() {       })

该回调函数的不接受任何参数

promise是一个对象,代表一个异步操作,有三种状态,进行中,成功,失败。只有异步操作的结果的可以决定当前是哪种状态,promise一旦新建执行,就没有办法中途停止。

Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。只有当作为参数所有的promise函数运行完毕,才会执行.then回调。

深入解析ES6中的promise

深入解析ES6中的promise

深入解析ES6中的promise

//以往回调方式 函数1(function(){     //代码执行...(ajax1)          函数2(function(){         //代码执行...(ajax2)                  函数3(function(data3){               //代码执行...(ajax3)         });         ...     }); });  //Promise回调方式:链式调用,可构建多个回调函数。 promise().then().then()...catch()
 //创建Promise实例 let promise = new Promise( (resolve, reject) => {     //执行相应代码 根据情况调用resolve或reject     ... })  //promise的then方法中执行回调 promise.then(function(){         //第一个参数是返回resolve时     },function(){         //第二个是回调返回reject时     } }

定时器调用

const promise = new Promise(function(resolve, reject){     setTimeout(resolve,1000); })  promise.then(function(){   console.log('resolve:成功回调函数')   },function(){   console.log('reject:失败回调函数') })

深入解析ES6中的promise

传递参数:

const promise = new Promise((resolve, reject) => {     setTimeout(reject,1000,'我是value值'); })  promise.then((value) => {     console.log('resolve:' + value) }).catch((value) => {     console.log('reject:'+ value) })  //第一种,单个传值是无效的 const promise = new Promise((resolve, reject) => {     setTimeout(resolve,1000,'参数1','参数2'); })  promise.then((value1,value2) => {     console.log('value1:' + value1)     //value1:参数1     console.log('value2:' + value2)     //value2:undefined }).catch((value) => {     console.log(value) })  //第二种:数组传值 const promise = new Promise((resolve, reject) => {     setTimeout(resolve,1000,['参数1','参数2']); }) promise.then((value1) => {     console.log('value1:' + value1)     //value1:参数1,参数2 }).catch((value) => {     console.log(value) }) 

Promise.prototype.then方法:链式操作

getJSON("/posts.json").then(function(json) {   return json.post; }).then(function(post) {   // proceed });

Promise.prototype.catch方法:捕捉错误

getJSON("/posts.json").then(function(posts) { }).catch(function(error) {   console.log('发生错误!', error); });

Promise.all方法,Promise.race方法

var p = Promise.all([p1,p2,p3]);  var p = Promise.race([p1,p2,p3]);

❤️ 不要忘记留下你学习的脚印 [点赞 收藏 评论]

作者Info:

【作者】:Jeskson

【原创公众号】:达达前端小酒馆。

【转载说明】:转载请说明出处,谢谢合作!~

关于目前文章内容即涉及前端,PHP知识点,如果有兴趣即可关注,很荣幸,能被您发现,真是慧眼识英!也感谢您的关注,在未来的日子里,希望能够一直默默的支持我,我也会努力写出更多优秀的作品。我们一起成长,从零基础学编程,将 Web前端领域、数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯。


若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。


请点赞!因为你们的赞同/鼓励是我写作的最大动力!

欢迎关注达达的CSDN!

这是一个有质量,有态度的博客

深入解析ES6中的promise

原创文章,作者:pydata

本文来自投稿,不代表 怪小克 立场,如若转载,请注明出处:https://wangchaoke.cn/?p=1185

本站发布的内容若侵犯到您的权益,请邮件联系 860095347@qq.com 删除,我们将及时处理!

发表评论

电子邮件地址不会被公开。 必填项已用*标注

联系我们

860-095-347

在线咨询:点击这里给我发消息

邮件:860095347@@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code