一、什么是promise?我们用promise解决什么样的问题
promise是异步编程的一种解决方案:从语法上来说,Promise是一个对象,从他可以获取异步操作的信息;从本意上讲,它是承诺,它承诺过一段时间会给你一个答复。Promise有三种状态:pending(等待态)、fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。
Promise常常用来解决两个问题:
- 回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
- promise可以支持多个并发的请求,获取并发请求中的数据
- 这个promise可以解决异步的问题,本身不能说promise是异步的
二、Promise 用法大全
1、基础用法
let p = new Promise( (resolve, reject) => { console.log('我刚刚进来') setTimeout(() => { console.log('执行成功'); resolve('我是成功'); reject('我是失败'); }, 2000); console.log('我在函数的末尾') }); p.then( (data) => { console.log(data) })
// 执行结果
// 我刚刚进来
// 我在函数的末尾
// 执行成功
// 我是成功
- resolve :异步操作执行成功后的回调函数
- reject:异步操作执行失败后的回调函数
2、链式编程
p.then( (data) => { console.log(data); return '我是第一个then' }) .then( (data) => { console.log(data); return () => { console.log('我是第二个then的方法') } }) .then( (fun) => { fun(); })
所以,从表面上看,Promise只是能够简化层层回调的写法,而实质上,Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活的多。所以使用Promise的正确场景是这样的:
3、reject的用法(失败状态)
let p2 = new Promise( (resolve, reject) => { setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (num > 5 ) { resolve(`${num}大于5,成功了`) } else { reject(`${num}小于5,失败了`) } }, 2000) }); p2.then((data) => { console.log('resolve', data) }, (err) => { console.log('reject', err) }); // 执行结果 // reject 1小于5,失败了 // resolve 8大于5,成功了
用来处理失败的情况
4、catch的用法
我们知道Promise对象除了then方法,还有一个catch方法,它是做什么用的呢?其实它和then的第二个参数一样,用来指定reject的回调。用法是这样:
p.then((data) => { console.log('resolved',data); console.log(err); //此处的err未定义 }) .catch((err) => { console.log('rejected',err); });
catch在Promise中的任何一步出现异常都不会卡死js的运行,而是会进入到这个catch中。catch类似于 try - catch;
5.all 的用法
let Promise1 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1) { resolve(`${num}大于5,Promise1成功了`) } else { reject(`${num}小于5,Promise1失败了`) } }, 2100) }) let Promise2 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1 ) { resolve(`${num}大于5,Promise2成功了`) } else { reject(`${num}小于5,Promise2失败了`) } }, 2200) }) let Promise3 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1 ) { resolve({'ccc': `${num}大于5,Promise3成功了`}) } else { reject(`${num}小于5,Promise3失败了`) } }, 2300) }) let pall = Promise.all([Promise1, Promise2, Promise3]) pall.then((data) => { console.log(data, '成功') }, (err) =>{ console.log(err, '失败') }) // 执行结果 // [ '4大于5,Promise1成功了', // '8大于5,Promise2成功了', // { ccc: '9大于5,Promise3成功了' } ] '成功'
all方法: 谁跑的慢,就以谁为执行准执行回调。all接收一个数组参数,里面的值最终都返回到Promise对象中。
有了all方法,就可以一次执行多个异步操作,并且可以统一处理返回结果。例:在打开一个页面是可以统一加载一些配置信息,比如下拉框选项等资源。
6、race用法
let p2 = new Promise( (resolve, reject) => { setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (num > 5 ) { resolve(`${num}大于5,成功了`) } else { reject(`${num}小于5,失败了`) } }, 5000) }); let Promise3 = new Promise(function(resolve, reject){ setTimeout(() => { let num = Math.ceil(Math.random() * 10); if (1 ) { resolve({'ccc': `我执行的快,就我了`}) } else { reject(`${num}小于5,Promise3失败了`) } }, 2300) }) Promise.race([p2, Promise3]).then((data) =>{ console.log(data); }).catch((err) => { console.log(err); }); // { ccc: '我执行的快,就我了' }
reac用来处理加载超时的情况。