Promise简介、promise.all与race应用

本人前端小白,项目经历较少,遇到页面接口请求较多时总会有些疑惑,不知道怎么处理合理。看之前的项目代码,写了不知多少回调,最近整理promise.all和async/await两个方法,分享一下。同时结合两者优化下接口性能,减少请求耗时。

Promise

众所周知,Promise 是一个对象,用于表示一个异步操作的最终完成 (或失败), 及其结果值。

语法:new Promise( (resolve, reject) => {...} /* executor */ );

let promise = new Promise((resolve,reject) => {
    resolve('success')
     // or
    reject('error')
})

该对象接收两个参数

  • resolve: 将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去.
  • reject: 将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
promise.then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

then方法会返回一个Promise,接收一个回调函数作参数,回调函数接受Promise对象传出的值作为参数

Promise.all()

将多个promise实例包装成一个新的promise实例,接收一个数组作参数。成功时返回一个数组,数组中包括所有子promise的结果;失败时,返回第一个失败promise的结果。

let p1 = new Promise((resolve,reject) => {
   resolve('success1')
   //reject('error')
})
let p2 = new Promise((resolve,reject) => {
    resolve('success2')
 })
 let p3 = new Promise((resolve,reject) => {
    reject('error')
 })

成功状态时:

Promise.all([p1,p2]).then(res => {
     console.log(res)
 }).catch(err => {
     console.log(err)
 })
 
 // 返回结果
 
 ['success1', 'success2' ]

失败时:

 Promise.all([p1,p2,p3]).then(res => {
     console.log(res)
 }).catch(err => {
     console.log(err)
 })
 
 // 输出
 error

注意:

  • 成功时返回数组中,值的顺序跟传入参数中promise实例的顺序对应,类似于同步执行,不会因为返回结果耗时的影响。

适用场景:

  • 页面请求过多时,可根据Promise.all()返回结果判断所有请求是否成功,否则使页面一直处于loading状态,避免用户操作,或者提是错误。
  • 发送多个请求,需要根据请求顺序获取和使用数据的场景。
  • 避免promise使用不合理或各种回调函数造成地狱回调,无法维护。

Promise.race()

用法同Promise.all(),哪个子promise结果先被返回,就返回该结果,不管是成功还是失败状态。

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  },1000)
})

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('error')
  }, 500)
})

Promise.race([p1, p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)  // 'error'
})

async/await

  • 见名知意: 异步与等待
  • 同步思维解决异步问题的方案。

async

函数使用async后将转换成Promise,并且其返回值也是一个Promise。

async function fn() {
    console.log('async')
    return 1
}
fn()

// 结果
async
Promise {<resolved>: 1}

如果函数内部未使用return,resolved的值为undefind。(最好在浏览器上尝试,node上有返回promise,但无法显示,可能我的node4版本较低)

  • 既然返回值是Promise,那我们变可以使用then()获取。
async function fn() {
    console.log('async')
    return 1
}
fn().then(res => {
    console.log(res) // 1
})

await

  • await只能在async函数内部使用,用在普通函数里就会报错

结合实际开发来说明

fetch('https://blog.csdn.net/')
  .then(res => {
    console.log(res)
    return fetch('https://juejin.im/')
  })
  .then(res => {
    console.log(res)
  })
  .catch(error => {
    console.log(error)
  })
  • 这种代码可能大家都有见过,虽然能体现等待的效果,但当链式调用过多,将充斥着多个then,配合业务逻辑那就部那么语义化,且难以维护。
async function foo () {
  try {
    let response1 = await fetch('https://blog.csdn.net/')
    console.log(response1)
    let response2 = await fetch('https://juejin.im/')
    console.log(response2)
  } catch (err) {
    console.error(err)
  }
}
foo()

  • 上面代码,整个异步处理的逻辑都是使用同步代码的方式来实现的,感觉就在写同步代码,比较符合人的线性思维的。
  • await 后面一定是Promise 对象,如果不是会自动包装成Promise对象。

promise.all与async/await结合,优化请求

先看个栗子

function fn1() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p1')
        },1000)
    })
}
function fn2() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p2')
        },2000)
    })
}
async function fn() {
    let p1 = await fn1()
    let p2 = await fn2()
}
 
 fn()

忽略浏览器引擎的耗时,fn1,fn2理想总共耗时3000毫秒

function fn1() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p1')
        },1000)
    })
}
function fn2() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p2')
        },2000)
    })
}

async function fn() {
    let [res1, res2] = await Promise.all([test1(), test2()])
}
fn()

而这种写发理想耗时2000ms,因为promise.all是将多个异步操作并行实现。
需要注意的是,多个await命令不存在依赖关系。

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

推荐阅读更多精彩内容

  • 透彻掌握Promise的使用,读这篇就够了 Promise的重要性我认为我没有必要多讲,概括起来说就是必须得掌握,...
    穿牛仔裤的蚊子阅读 2,133评论 0 16
  • async 函数 含义 ES2017 标准引入了 async 函数,使得异步操作变得更加方便。 async函数对 ...
    Xyaleo阅读 1,093评论 0 4
  • 含义 async函数是Generator函数的语法糖,它使得异步操作变得更加方便。 写成async函数,就是下面这...
    oWSQo阅读 1,991评论 0 2
  • async 函数 含义 ES2017 标准引入了 async 函数,使得异步操作变得更加方便。 async 函数是...
    huilegezai阅读 1,259评论 0 6
  • async 函数 ES2017 标准引入了 async 函数,使得异步操作变得更加方便。async 函数是什么?一...
    _羊羽_阅读 2,103评论 0 1