一、Promise 是什么
Promise 是 ES6 提供的原生对象,用来处理异步操作
它有三种状态
pending: 初始状态,不是成功或失败状态。
fulfilled: 意味着操作成功完成。
rejected: 意味着操作失败。
二、使用
2.1 创建 Promise
通过 new Promise 来实例化,支持链式调用
1 2 3 4 5 6 7
| new Promise((resolve, reject)=>{ }).then(()=>{ }).catch(()=>{ })
|
2.2 执行顺序
Promise一旦创建就立即执行,并且无法中途取消,执行逻辑和顺序可以从下面的示例中获得
如下,可修改 if 条件来改变异步结果,下面打印开始的数字是执行顺序
在线调试此示例 - jsbin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| console.log('1.开始创建并执行 Promise') new Promise(function(resolve, reject) { console.log('2.由于创建会立即执行,所以会立即执行到本行') setTimeout(()=>{ console.log('4. 1s之期已到,开始执行异步操作') if (true) { resolve('成功') } else { reject('不符合预期') } }, 1000) }).then((res)=>{ console.log('5.调用了then,接收数据:' + res) }).catch((error)=>{ console.log('5.调用了catch,错误信息:' + error) }) console.log('3.本行为同步操作,所以先于 Promise 内的异步操作(setTimeout)')
|
执行结果如下
1 2 3 4 5
| "1.开始创建并执行 Promise" "2.由于创建会立即执行,所以会立即执行到本行" "3.本行为同步操作,所以先于 Promise 内的异步操作(setTimeout)" "4. 1s之期已到,开始执行异步操作" "5.调用了then,接收数据:成功"
|
2.3 用函数封装 Promise
这是比较常用的方法,如下用 setTimeout 模拟异步请求,封装通用请求函数
在线调试此示例 - jsbin
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function ajax(url){ return new Promise(resolve=>{ console.log('异步方法开始执行') setTimeout(()=>{ console.log('异步方法执行完成') resolve(url+'的结果集') }, 1000) }) }
ajax('/user/list').then((res)=>{ console.log(res) })
|
执行结果
1 2 3
| "异步方法开始执行" "异步方法执行完成" "/user/list的结果集"
|
三、高级用法
3.1 同时支持Callback与Promise
在线调试此示例 - jsbin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| function ajax(url, success, fail) {
if (typeof success === 'function') { setTimeout(() => { if (true) { success({user: '羊'}) } else if (typeof fail === 'function') { console.log(typeof fail) fail('用户不存在') } }, 1000) } else { return new Promise((resolve, reject) => { this.ajax(url, resolve, reject) }) }
}
ajax('/user/get', (res)=>{ console.log('Callback请求成功!返回结果:', res) }, (error)=>{ console.log('Callback请求失败!错误信息:', error) })
ajax('/user/get').then((res)=>{ console.log('Pormise请求成功!返回结果:', res) }).catch((error)=>{ console.log('Promise请求失败!返回结果:', error) })
|
执行结果
1 2
| Callback请求成功!返回结果: {user: "羊"} Pormise请求成功!返回结果: {user: "羊"}
|
3.2 链式调用
.then 支持返回 Promise 对象进行链式调用
1 2 3 4 5 6 7 8 9 10
| ajax('/user/info').then((res)=>{ console.log('用户信息:', res) return ajax('/user/score') }).then((res)=>{ console.log('用户成绩:', res) return ajax('/user/friends') }).then((res)=>{ console.log('用户朋友:', res) })
|
3.3 Promise.all
Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
在线调试此示例 - jsbin
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| var promises = [2, 3, 5, 7, 11, 13].map(function(id){ return new Promise((resolve, reject)=>{ if (id % 3 === 0) { resolve(id) } else { reject(id) } }); }); Promise.all(promises).then(function(post) { console.log('全部通过') }).catch(function(reason){ console.log('未全部通过,有问题id:'+reason) });
|
执行结果
Reference
mozilla web docs