Js中有使人头疼的地狱回调的问题,因而有了Promise,有了链式调用,基于Promise也出现了各类异步解决方案就出现了,其中最好的我的感受应该是async/await的解决方案了,一直以来都是模模糊糊的使用,直到碰见了循环与异步的问题,因而花时间查阅资料从1分懂到了4分懂.javascript
网上关于Promise的文章有不少,也讲得很好,这里也简单的记录一下.java
Promise不只经过链式调用解决了回调嵌套的问题,还解决了回调函数中使用 return 和 throw 的问题,最重要的是它在异步解决方案中的使用.
Promise一共拥有pending/resloved/rejected(进行中/已完成/已失败)这三个状态,resloved/rejected状态能够由pendding状态变化获得,并且这个状态一旦变化就不会再更改.数组
Promise.all()
// 多个Promise并行进行,当全部Promise reslove时reslove.当有一个Promise reject时rejectPromise.race()
// 与Promise.all相似,差异在当第一个Promise reslove时reslove.Promise.then()
// 用于链式调用Promise.catch()
// 捕获rejectfunction sleep(dely) { return new Promise((reslove) => { setTimeout(() => { console.log(`dely ${dely}s`) reslove(); }, dely * 1000); }) } (async () => { console.log('before sleep') await sleep(2); console.log('after sleep') })() /** console * before sleep * dely 2s * after sleep */
这个是ES7中的异步解决方案,在Node v8.0.0及其以上已经原生支持,在低版本的Node中须要开启--harmony-async-await
选项异步
例若有以下设定: 每一个人的碎觉时间都是固定值,若是有多我的碎觉,则后一我的的碎觉时间是前面碎觉时间的累积和,写一个函数在传入name数组时能实现以上描述,话很少说上代码async
const users = { // 定义3我的,且每一个人睡觉时间是1 leo: { name: 'leo', sleep: 1 }, mick: { name: 'mick', sleep: 1 }, jack: { name: 'jack', sleep: 1 } } function sleep(name, sleep) { // 碎觉函数,包括打印当前碎觉时间,和累加未碎觉人的时间 return new Promise((reslove) => { setTimeout(() => { console.log(`${name} sleep ${sleep}`); Object.keys(users).forEach(u => { if (name !== u) { users[u].sleep += sleep; } }) reslove(); }, sleep * 1000); }) }
我第一次写出来是这样的函数
(function consoleSleep(names) { return Promise.all(names.map(async n => { await sleep(users[n].name, users[n].sleep) })) }(['leo', 'mick', 'jack'])) /** console * leo sleep 1 * mick sleep 1 * jack sleep 1 */
当场我就很懵逼,把name 数组拿来循环,而后循环中等待当前sleep时的各类异步操做,但结果让人很忧桑,在分析问题后,发现这是一个串行执行异步操做的问题,
好吧,Promise.all()
是并行进行的,但是在去掉Promise.all后结果任然没有改变,通过各类查资料后发现是map的问题(笑哭)(map和forEach都是并行迭代的),好吧再改代码学习
(async function consoleSleep(names) { for(let i = 0; i < names.length; i++) { await sleep(users[names[i]].name, users[names[i]].sleep) } }(['leo', 'mick', 'jack'])) /** console * leo sleep 1 * mick sleep 2 * jack sleep 4 */
终于实现了功能,大功告成code
Promise不只解决了回调嵌套还提供了异步解决的方式,可使用Promise封装异步操做而后使用async/await来把异步操做变成同步的,在循环中使用Promise时要注意并行和串行两种方式带来的不一样操做结果,固然其它库也提供了相应封装的方法(例如bluebird有mapSeries能够直接迭代串行执行多个Promise).
ps: 学习了,map/forEach是并行的迭代,而不是同步的循环,切记!切记!切记!对象