ES6 Promise对象解决异步回调
2018-02-27 19:48
405 查看
resolve和
reject。它们是两个函数,由JavaScript引擎提供,不用自己部署。Promise实例生成以后,可以用
then方法分别指定
Resolved状态和
Reject状态的回调函数。
什么是Promise
Promise最早由社区提出并实现,典型的一些库有Q,when, bluebird等;它们的出现是为了更好地解决JavaScript中异步编程的问题,传统的异步编程最大的特点就是地狱般的回调嵌套,一旦嵌套次数过多,就很容易使我们的代码难以理解和维护。而Promise则可以让我们通过链式调用的方法去解决回调嵌套的问题,使我们的代码更容易理解和维护,而且Promise还增加了许多有用的特性,让我们处理异步编程得心应手。如何创建Promise
ES6给我们提供了一个原生的构造函数Promise,我们可以看一下这个构造函数:// 下面的代码可以直接运行在浏览器的控制台中(Chrome浏览器) > typeof Promise "function" // 可以看出这是一个构造函数 > Promise function Promise() { [native code] } // ES6的原生支持下面我们先来创建一个promise,下面是一个简单的示例:
// 我们先使用ES5的语法 var promise = new Promise(function(resolve, reject) { var flag = Math.random(); setTimeout(function() { if(flag) { resolve('success'); } else { reject('fail'); } }, 1000); }); console.log(promise); // 在浏览器的控制台运行的话,它返回的是一个包含了许多属性的Promise对象;在Node.js环境中控制台输出 Promise { <pending> }。 promise.then(function(result) { console.log(result); }, function(err) { console.log(err); }); // 1s后这里的输出可能是fail也可能是success下面来解释一下上面的代码:因为Promise是一个构造函数,所以我们使用了new操作符来创建promise。
构造函数Promise的参数是一个函数(暂时叫它func),这个函数(func)有两个参数resolve和reject,它们分别是两个函数,这两个函数的作用就是将promise的状态从pending(等待)转换为resolved(已解决)或者从pending(等待)转换为rejected(已失败)。
创建后的promise有一些方法,then和catch。当然我们也可以人为的在Promise函数上添加一些满足我们自己需求的方法,方便每一个promise对象使用。
如果我们使用一些ES6的语法的话,我们上面的代码会更加简洁:
let p = new Promise((resolve, reject) => { setTimeout(() => { Math.random() > 0.5 ? resolve('success') : reject('fail'); }, 1000) }); console.log(p); p.then((result) => { console.log(result); }, (err) => { console.log(err); });其实可以这样理解,Promise函数体的内部包裹着一个异步的请求或者操作或者函数;然后我们可以在这个异步的操作完成的时候使用resolve函数将我们获得的结果传递出去,或者使用reject函数将错误的消息传递出去。
Promise对象的一些方法
Promise对象可以通过使用then方法将上一步返回的结果获取过来(不管是resolved还是rejected),可以通过使用catch方法捕获Promise对象在使用catch之前的异常。首先来说一下then方法的使用:let p = new Promise((resolve, reject) => { let flag = Math.random() > 0.5 ? true : false; if(flag) { console.log('使用resolve将promise状态从pending变为resolved'); resolve('success'); } else { console.log('使用reject将promise状态从pending变为rejected'); reject('fail'); } }); // @1 p.then((result) => { console.log('接受resolved的结果'); console.log(result); }, (err) => { console.log('捕获错误的结果'); console.log(err); });我们可以看到,then方法可以接受两个函数作为参数,第一个函数是用来处理resolve的结果,第二个是可选的,用来处理reject的结果。也就是说,我们在创建p这个Promise对象的时候,通过函数resolve传递出去的结果可以被p的第一个then方法中的第一个函数捕获然后作为它的参数。通过函数reject传递出去的结果可以被p的第一个then方法中的第二个函数捕获然后作为它的参数。当然我们还可以在每一个then方法中创建新的Promise,然后将这个Promise对象返回,之后我们就可以在后面的then方法中继续对这个对象进行操作。下面是一个简单的例子:
let p1 = new Promise((resolve, reject) => { let flag = Math.random() > 0.5 ? true : false; resolve(); }); // @2 使用then方法进行链式的调用 p1.then(() => { return 1; }).then((result) => { console.log(result); return 'hello' }).then((result) => { console.log(result); }); // @3 在then方法内部可以再次使用异步的操作 p1.then(() => { console.log('******'); let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve(123); }, 1000); }); return p1; }).then((result) => { console.log(result); });从上面的代码中我们可以看到,一旦创建一个Promise对象之后,我们就可以使用then方法来进行链式的调用,而且我们可以把每一次的结果都返还给下一个then方法,然后在下一个then方法中对这个值进行处理。每一个then方法中都可以再次新创建一个Promise对象,然后返还给下一个then方法处理。Promise还有另一个方法catch,这个方法其实是then方法的一种特例,这个特例就是:
.then(null, rejection)相当于我们不使用then方法的第一个函数,只是用第二个函数;catch函数比较简单,就是用来捕获之前的then方法里面的异常,我们可以简单的来看一个例子:
let p = new Promise((resolve, reject) => { resolve(); }); p.then(() => { console.log('progress...'); }).then(() => { throw new Error('fail'); }).catch((err) => { console.log(err); });上面代码的输出结果如下:
progress... VM141:9 Error: fail(…)我们可以使用catch函数来捕获整个then函数链中的异常。
Promise的一些方法
Promise.all方法用来包装许多个Promise实例,然后组成了一个新的Promise对象,新的Promise对象的状态由前面几个被包裹的Promise对象的状态决定,如果前面的Promise都被resolve了,那么新的Promise的状态也是resolve的;只要有一个Promise被reject了,那么组成的新的Promise的状态也是reject的。可以看下面一个例子:let arr = [1, 2, 3].map( (value) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(value); }, value * 1000); }); } ); console.log(arr); let promises = Promise.all(arr) .then((result) => { console.log(result); }).catch((err) => { console.log(err); });上面的代码的输出结果如下:
[ Promise { <pending> }, Promise { <pending> }, Promise { <pending> } ] [ 1, 2, 3 ] // 3s后输出的结果Promise.race方法和上面的Promise.all有点类似,都是包装许多的Promise对象,然后组成了一个新的Promise对象,但是使用Promise.race的含义是:只要包裹的的Promise对象中有一个的状态发生了改变,那么组成的这个新的Promise对象的状态就是上面那个率先改变的Promise实例的状态。下面是一个简单的例子:
let arr = [1, 2, 3].map( (value) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(value); }, value * 1000); }); } ); console.log(arr); let promises = Promise.race(arr) .then((result) => { console.log(result); }).catch((err) => { console.log(err); });上面程序的输出结果如下:
[ Promise { <pending> }, Promise { <pending> }, Promise { <pending> } ] 1 // 是最先改变状态的那个Promise实例resolve的值Promise.resolve方法主要是将一个值转变为一个Promise对象,然后使它具有Promise的一些方法和特性,为了满足我们一些特殊情况下的要求。下面是一个简单的例子:
let arr = [null, 0, 'hello', { ce2c then: function() { console.log(' a thenable obj')}} ]; arr.map((value) => { return Promise.resolve(value); }); console.log(arr);上面的输出结果如下:
[ null, 0, 'hello', { then: [Function: then] } ] a thenable obj // Promise.resolve方法会将具有then方法的对象转换为一个Promise对象,然后就立即执行then方法。Promise.reject方法和Promise.resolve方法一样,只不过通过Promise.reject方法产生的Promise对象的状态是rejected的,下面是一个示例:
let p = Promise.reject('fail'); p.catch((err) => { console.log(err); }); // fail上面的内容把ES6中新增的Promise的基本使用方法给大家讲了一下,希望对大家有多帮助。好啦,就先到这里吧。作者:dreamapplehappy
链接:https://zhuanlan.zhihu.com/p/23907711
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
相关文章推荐
- 使用ES6的Promise完美解决回调地狱
- ES6中的异步对象Promise
- ES6中promise对象——告别回调的嵌套
- 使用ES6的Promise完美解决回调地狱
- ES6/7/8新特性Promise,async,await,fetch带我们逃离异步回调的深渊
- 使用ES6的Promise完美解决回调地狱
- jQuery的promise与deferred对象在异步回调中的作用
- jQuery的promise与deferred对象在异步回调中的作用
- Angular使用Promise解决多个异步回调问题
- 使用ES6的Promise完美解决回调地狱
- 再不用ES6就Out了--Promise解决回调地狱
- 浅析 Angular $q promise 回调异步嵌套解决机制
- ES6 - Promise对象,异步操作
- javascript异步代码的回调地狱以及JQuery.deferred提供的promise解决方式
- 使用Promise链式调用解决多个异步回调的问题
- Promise对象(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败
- 谈谈 ES6 的 Promise 对象
- ES6中Promise对象个人理解
- 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise
- 前端基本知识(四):JS的异步模式:1、回调函数;2、事件监听;3、观察者模式;4、promise对象