博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6 Promise介绍
阅读量:7101 次
发布时间:2019-06-28

本文共 4355 字,大约阅读时间需要 14 分钟。

  • 作者:Leo晓华

回调地狱

由于 JavaScript 的单线程性质,我们必须等待上一个请求返回结果后才能处理下一步,如下:

$.ajax({   url: "/step1",   success: function(){      $.ajax({         url: "/step2",         success: function(){            $.ajax({               url: "/step3",               success: function(){              }            });        }      });  }});复制代码

这种回调地狱嵌套层级多了,代码结构就容易变得很不直观,可读性比较差。

Promise 是 ES6原生支持的,把原来嵌套的回调改为了级联的方式。

了解Promise

Promise 可以简单理解为一个事务,这个事务存在三种状态:

  • 已经完成了 resolved(完成态)
  • 因为某种原因被中断了 rejected(失败态)
  • 初始状态 pending(未完成)

注意,这种状态的改变只会出现从未完成态向完成态或失败态转化,不能逆反。完成态和失败态不能互相转化,而且,状态一旦转化,将不能更改。

只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思是承诺,表示其他手段无法改变。

例子:

var p = new Promise(function (resolve, reject) {    if(/* 异步操作成功 */){        resolve(ret);    } else {        reject(error);    }});复制代码

在声明一个Promise对象实例时,我们传入的匿名函数参数中:

resolve 就对应着完成态之后的操作
reject 对应着失败态之后的操作

Promise的then方法

p.then(function (value) {    // 完成态,value是上面resolve传入的值}, function (error) {    // 失败态,error是上面reject传入的值});复制代码

then()方法传递的两个参数中:

  • 第一个参数(函数)对应着完成态的操作,也就是resolve时调用

  • 第二个参数(函数)对应着失败态的操作,也就是reject时调用

  • 第二个参数可以没有

多个promise链式

例子1:

var p1 = new Promise((resolve, reject) => {    setTimeout(() => resolve('p1'), 1000);});p1.then( ret => {    console.log(ret); //p1    return'then1';}).then( ret => {    console.log(ret); //then1    return'then2';}).then( ret => {    console.log(ret); //then2});复制代码

在 resolve 之前,promise 的每一个 then 都会将回调函数压入队列,resolve 后,将 resolve 的值送给队列的第一个函数,第一个函数执行完毕后,将执行结果再送入下一个函数,依次执行完队列。一连串下来,一气呵成,没有丝毫间断。

链式中的then方法(第二个开始),它们的resolve中的参数是什么?答案就是前一个then()中resolve的return语句的返回值。

例子2:

step1:function(){        var promise = new Promise(function(resolve,reject){             $.ajax({                url:"/step1",                    success:function(data){                        resolve(data)//在异步操作成功时调用                    }            });        })        return promise;    },    step2:function(val){        var promise = new Promise(function(resolve,reject){            $.ajax({                url:"/step2",                    data:val,   //来自step1的参数                    success:function(data){                        resolve(data)//在异步操作成功时调用                    }                });            })            return promise;        }    step1()    .then(data => return step2(data))  //step1的结果传给step2作为参数    .then(data => console.log(data))复制代码

错误处理

方法1:由then的第二个处理函数处理错误

var p = new Promise(function (resolve, reject) {    // ...    if(/* 异步操作成功 */){        resolve(ret);    } else {        reject(error);    }});p.then(function (value) {    // 完成态}, function (error) {    // 失败态});复制代码

方法2:链式错误处理 (catch 方法)

var p = new Promise(function (resolve, reject) {    // ...    if(/* 异步操作成功 */){        resolve(ret);    } else {        reject(error);    }});p.then(function (value) {    // 完成态}).then(function (value) {    // 完成态}).catch( err => {// 可以捕抓到前面的出现的错误。    console.log(err.toString());});复制代码

如果第一个then报错,第二个then不会执行。

一个活动项目的例子:

//查用户信息querymystate(){    var promise = new Promise(function(resolve,reject){        utils.get('/querystate', {          raffle_code:xxx,        }, (rst) => {          if (rst.return_code === 0) { //成功获取用户信息                resolve(rst.data);                                  } else { //获取失败              reject(rst.error_message);              }        })        })        return promise;},//我要领奖,必须先获取用户信息getAward(){    querymystate()    .then(data => {      //领奖处理    }).catch(ErrMsg => {      //弹出错误提示ErrMsg    })}复制代码

Promise.all()

Promise.all()方法用于将多个Promise实例,包装成一个新的Promise实例,例如:

var p = Promise.all([p1, p2, p3]);复制代码

新的Promise实例p的状态由p1, p2, p3决定:

  • 当p1, p2, p3的状态都为完成态时,p为完成态。

  • p1, p2, p3中任一一个状态为失败态,则p为失败态。

例子:

let a = new Promise((resolve, reject) => {     setTimeout(() => {       resolve(2)     }, 2000)   }) let b = new Promise((resolve, reject) => {     setTimeout(() => {       resolve(3)     }, 2000)   }) Promise.all([a, b]).then( (ret) => console.log(ret)) //2秒后,注意这里返回的是数组 [2,3].catch( err => console.log(err.toString()));复制代码

Promise.race()

race意思是赛跑,看谁先到。只要p1, p2, p3中任意一个实例率先改变状态,则p的状态就跟着改变,而且状态由率先改变的实例决定。

let a = new Promise((resolve, reject) => {     setTimeout(() => {       resolve(2)     }, 3000)   }) let b = new Promise((resolve, reject) => {     setTimeout(() => {       resolve(3)     }, 2000)   }) Promise.race([a, b]).then( (ret) => console.log(ret)) //2秒后显示3.catch( err => console.log(err.toString()));复制代码

转载地址:http://cfrql.baihongyu.com/

你可能感兴趣的文章
UILabel里字体带下划线2
查看>>
loadrunner字符串处理函数
查看>>
20165320 第四周课下补做
查看>>
布局文件中fill_parent和match_parent有什么区别?
查看>>
HTTP报文内的HTTP信息
查看>>
sublime使用技巧(1)-- 下载与插件安装
查看>>
linux 自定义快捷命令
查看>>
学习Spark——环境搭建(Mac版)
查看>>
tsung的压力测试
查看>>
Linux常用命令之文件搜索命令
查看>>
H5移动前端开发常用高能css3汇总
查看>>
bzoj1618[Usaco2008 Nov]Buying Hay 购买干草*
查看>>
【原】无脑操作:Eclipse + Maven + jFinal + MariaDB 环境搭建
查看>>
快速幂
查看>>
再谈javascript函数节流
查看>>
周掌柜
查看>>
分布式事务
查看>>
突发奇想
查看>>
强引用、软引用、弱引用、虚引用有什么区别
查看>>
【leetcode】Department Top Three Salaries
查看>>