共计 1717 个字符,预计需要花费 5 分钟才能阅读完成。
JavaScript 的世界中,所有代码都是单线程执行的。异步执行可以用回调函数实现,但是某些场景并不好用,且不易复用。Promise 对象这种链式写法的好处在于,先统一执行逻辑,不关心如何处理结果,然后,根据结果是成功还是失败,在将来的某个时候调用 success 函数或 fail 函数。
Pomise.all 的使用
Promise.all
可以将多个 Promise
实例包装成一个新的 Promise 实例。同时,成功和失败的返回值是不同的,成功的时候返回的是 一个结果数组 ,而失败的时候则返回 最先被 reject 失败状态的值。
Promise.all 中传入的是数组,返回的也是是数组,并且会将进行映射,传入的 promise 对象返回的值是按照顺序在数组中排列的,但是注意的是他们执行的顺序并不是按照顺序的,除非可迭代对象为空。
可迭代对象:
遍历 Array 可以采用下标循环,遍历 Map 和 Set 就无法使用下标。为了统一集合类型,ES6 标准引入了新的 iterable 类型,Array、Map 和 Set 都属于 iterable 类型。具有 iterable 类型的集合可以通过新的 for … of 循环来遍历。
示例代码如下:
let p1 = new Promise((resolve, reject) => {resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {resolve('success')
})
let p3 = Promse.reject('失败')
Promise.all([p1, p2]).then((result) => {console.log(result) //['成功了', 'success']
}).catch((error) => {console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {console.log(result)
}).catch((error) => {console.log(error) // 失败了,打出 '失败'
})
Promse.all 在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个 ajax 的数据回来以后才正常显示,在此之前只显示 loading 图标。
代码模拟:
let wake = (time) => {return new Promise((resolve, reject) => {setTimeout(() => {resolve(`${time / 1000}秒后醒来 `)
}, time)
})
}
let p1 = wake(3000)
let p2 = wake(2000)
Promise.all([p1, p2]).then((result) => {console.log(result) // ['3 秒后醒来', '2 秒后醒来']
}).catch((error) => {console.log(error)
})
需要特别注意的是,Promise.all 获得的成功结果的数组里面的数据顺序和 Promise.all 接收到的数组顺序是一致的,即 p1 的结果在前,即便 p1 的结果获取的比 p2 要晚。这带来了一个绝大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用 Promise.all 毫无疑问可以解决这个问题。
Promise.race 的使用
顾名思义,Promse.race 就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
let p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('success')
},1000)
})
let p2 = new Promise((resolve, reject) => {setTimeout(() => {reject('failed')
}, 500)
})
Promise.race([p1, p2]).then((result) => {console.log(result)
}).catch((error) => {console.log(error) // 打开的是 'failed'
})