es6之promise

前言

前几天写代码的时候遇到了一个坑,async函数里面return的是一个promise对象,而不是我当时想要的某个值

getDeviceForm = async (formId, formName) => {
    const { storeId } = this.props.param;
    const { formMap } = this.state;
    const { ret, data } = await Request.get({
      uri: Request.getApiAddress('ENGINEERING', 'operation/form/device'),
      data: {
        formId,
        storeId,
      },
      useLoading: true,
    });
    return data;
  }

本想return一个对象,结果却返回给我一个promise对象,无论在后面加什么then函数return的值都是一个promise对象,


image

async函数会返回promise对象,把return的值放在promise里面
因此觉得还是没有理解async的原理.....😂回顾一下promise的知识点

一、promise的原理

promise就是一个异步得容器,里面保存着一个异步事件(在未来才会结束得事件,promise就是一个对象,从它可以获取异步操作得结果。

promise有两个特点

(1)promise不受外界影响,它代表一个异步操作,有三种状态:pending,fulfilled,rejected。只有异步操作的结果可以决定当前是哪种状态
(2)一旦状态改变,就不会在变化,任何时候都可以得到这个值,promise对象的状态改变只有两种,pending变为fulfilled,pending变为rejected,只要着两种情况发生,状态就凝固不变了,这时就称resolved

二、基本用法

2.1es6规定Promise对象是一个构造函数,用来生成promise实例
官方文档给出的实例
return一个promise对象,返回结果包含在内

promise接收一个函数作为参数,该函数接收两个参数,他们是resolve,reject两个函数

(1)resolve函数用来将promise对象从未完成变成 成功 (pending状态变为fulfilled状态),在异步操作成功时调用,并将异步操作结果作为参数传递出去,同理
(2)reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

promise生成后可以使用then方法指定成功失败的回调函数


image

then方法接收两个函数作为参数,第二个参数可以不传,两个函数都可以将promise返回结果作为参数传进来

举一个简单例子
var b = new Promise(() => resolve(1)); 
 b.then((value) => console.log(value)); //1   

then函数第一个参数作为接收resolve方法返回的promise返回对象作为参数传给console.log打印出来

2.2promise对象新建后就会立即执行
promise里面的代码会立刻执行

promise在异步队列里面优先级比settimeout高,此知识点是js的微任务宏任务的内容

2.3promise原型对象上的then方法

就来说一下最常用的then方法吧
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法,第二个then方法就会等待这个promise对象的结果

2.4promise原型对象上的catch方法
catch类似于try catch,用于捕获promise方法里的错误
2.5promise原型对象上的all方法

promise的all方法用来将多个promise实例包装成一个promise实例

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

p的状态又p1,p2,p3决定,分成两种情况

1.当p1,p2,p3都为fulfilled的时候,p的状态会变成fulfilled,此时p1,p2,p3的返回值会拼成一个数组返回给p的回调函数
2.当这三个有一个被rejected,p就变成rejected,此时第一个被rejected的值就会被返回给p的回调函数

情况1(都返回fulfilled状态)
情况2

注意,如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。下图是🌰


e2自己本身的catch
let p1 = new Promise((resolve, reject) => resolve(42))
let p2 = new Promise((resolve, reject) => reject(43))
let p3 = new Promise((resolve, reject) => resolve(44))

let p4 = Promise.all([p1, p2, p3])
let p5 = Promise.all([p1, p3])
p1.then(v=>console.log('p1 then: ' + v)) // p1 then: 42
p4.then(v=>console.log('p4 then: ' + v)) // Promise {<rejected>: 43}
p4.catch(v=>console.log('catch: ' + v)) // catch: 43 p2被拒绝,p4的拒绝处理函数立即调用,不会等p1和p3结束执行。但p1和p2仍然会执行。
p5.then(v=>{
  console.log(Array.isArray(v)) // true
  console.log(v) // [ 42, 44 ]
})
2.5promise原型对象上的race方法

有时面试会经常问的一个问题 promise.all和promise.race的区别

顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

race方法是只要有一个promise被解决,整个promise就被解决

let r1 = Promise.resolve('r41')
let r11 = Promise.reject('r41')
let r2 = new Promise((resolve, reject) =>{
  resolve('r42')
})
let r3 = new Promise((resolve, reject) =>{
  reject('rejcet43')
})
let r4 = Promise.race([r1, r2, r3])
r4.then(v=>console.log('r4: ' + v)) // r4: r41

let r5 = Promise.race([r2, r3])
r5.then(value => console.log('then:' + value)) // then:r42
r5.catch(value => console.log('catch:' + value)) // 不执行

let r6 = Promise.race([r11, r2, r3])
r6.then(v=>console.log('r6 then: ' + v))
r6.catch(v=>console.log('r6 catch: ' + v)) // r6 catch: r41

race和promise的区别在于:race是有一个promise被解决,整个promise就完成,无论其中一个是resolve还是reject。而all是其中一个被reject,则整个promise就停止,而resolve不会导致停止

2.6 为什么选择promise

以前的异步处理是用回调函数一层一层嵌套出来的结构,这样使开发者看起来很凌乱

step1(function(value1) {

step2(value1, function(value2) {

step3(value2, function(value3) {

step4(value3, function(value4) {

// Do something with value4

});

});

});

});

promise采用then方法接收异步结果,很清晰的链式结构

Q.fcall(function() {

return2;

}).then(function(val){

console.log(val);

//...

}).then(function(){

//...

}).done();

三、async函数原理

3.1 async是Generator 函数的语法糖,就是将Generator 函数和自动执行器,包装在一个函数里
image
3.2 async用法
async方法遇到await

async函数会返回一个promise对象
(1) 一遇到await就会先返回,等到返回的异步操作执行完成,再执行之后的代码,await后面跟着的是一个promise代码执行情况如上代码
(2)也可通过then添加回调函数,异步promise的结果返回到then的参数里面,代码如下

async function test () {
    return 'test async function'
}

test().then(
    result => console.log(result)
)

// 输出结果
// test async function

(3)注意点:await后面是一个promise,可能会出现异步操作失败的情况,所以将await命令放在try catch中

try里面执行如果遇到undefind或其他问题,错误提示就会出现在catch中参数msg里面

fetchOrderList = async () => {
    try {
      const data = await api.getReplenishDetail({ orderId: this.props.param.orderId });
      this.setState({
        dataSource: ds.cloneWithRows(data),
        total: data && data.length,
      });
    } catch (msg) {
      toolTip.show(msg || '获取补货详情失败');
    }
  }

连载async踩坑记录篇😅:
看此代码的执行顺序

上面代码打印结果

不是33应该在22的前面吗??

其实原因是我还没理解第一次踩坑的那句话 async函数返回的也是一个promise对象,对!就是返回一个promise,所以promise是一个异步方法,里面的环境里,setstate是同步的

记住一点,async函数返回的也是一个promise对象,return出去的是一个promise,血泪教训。。。。😂

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容

  • Promiese 简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,语法上说,Pr...
    雨飞飞雨阅读 3,358评论 0 19
  • 作者: kim先生 来源: 自创 今天我们讲的是ES6中的Promise这个异步操作对象。在学习Promise之前...
    前端进阶体验阅读 749评论 0 0
  • Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、c...
    HJHA阅读 286评论 0 0
  • Promise 对象 Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函...
    neromous阅读 8,706评论 1 56
  • 2017年五月底Node.js 8正式发布,带来了 很多新特性 。本文讨论下util.promisify()这个方...
    宛丘之上兮阅读 1,984评论 0 4