- Promise是做什么的
Promise是异步编程的一种解决方案。 - 什么时候我们会来处理异步事件
在开发时,比较常见的是在网络请求的时候处理异步操作。我们封装一个网络请求的函数,因为不能立即拿到结果,所以不能像简单的3+4=7一样将结果返回。所以往往我们会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。如果只是一个简单的网络请求,那么这种方案不会给我们带来很大麻烦。但是当网络请求很复杂时,就会出现回调地狱 - 考虑以下场景(夸张成分)
1.我们需要通过一个url1从服务器加载一个数据data1,data1中包含了下一个请求的url2
2.我们需要通过data1取出url2,从服务器加载数据data2,data2中包含了下一个请求的url3
3.我们需要通过data2取出url3,从服务器加载数据data3,data3中包含了下一个请求的url4
4.发送网络请求url4,最终获取数据data4
$ajax('url1',function(data1){
$ajax(data1['url2'],function(data2){
$ajax(data2['url3'],function(data3){
$ajax(data3['url4'],function(data4){
console.log(data4);
})
})
})
})
这样看来代码结构还是很清晰的,但是一般来说当我们拿到data1时不会立即去获取url2,data1要先处理业务,此时如果data1的业务代码有100行,然后才获取url2,再次发送网络请求,此时就会发现data1和第二层网络请求之间有100行代码,结构就会比较乱,此时如果其他data也需要处理业务,代码就会变得难以维护,难以管理。
那么如何才能用良好的方式处理这种异步操作呢?那就是使用Promise。
Promise基本语法
- 我们用一个定时器来模拟异步事件:
-假设下面的data时从网络上1s后请求的数据
-console.log就是我们的处理方式
//1.使用setTimeout
setTimeout(()=>{
console.log('hello,world');
setTimeout(() => {
console.log('hello Vue');
setTimeout(() => {
console.log('hello ES6');
},1000)
},1000)
},1000)
//参数 -> 函数(resolve,reject)
//resolve,reject本身又是函数
//链式编程
new Promise((resolve, reject) => {
//第一次网络请求的代码
setTimeout(() => {
resolve();
}, 1000)
}).then(() => {
// 第一次拿到结果的处理代码
console.log('hello,world');
return new Promise((resolve, reject) => {
//第二次网络请求的代码
setTimeout(() => {
resolve();
}, 1000)
})
}).then(() => {
// 第二次拿到结果的处理代码
console.log('hello Vue');
return new Promise((resolve, reject) => {
//第三次网络请求的代码
setTimeout(() => {
resolve();
}, 1000)
})
}).then(() => {
// 第三次拿到结果的处理代码
console.log('hello ES6');
})
// 什么情况下会用到Promise
// 一般情况下是有异步操作时,使用Promise对异步操作进行封装
// new -> 构造函数(1.保存了一些状态信息 2.执行传入的函数)
// 在执行传入的回调函数时,会传入俩个参数,resolve,reject本身又是函数
new Promise((resolve, reject) => {
setTimeout((data) => {
//成功的时候调用resolve
resolve('hello world');
// 失败的时候调用reject
reject('error message')
}, 1000)
}).then((data) => {
//1.100行的处理代码
console.log(data);
console.log(data);
console.log(data);
}).catch((err) => {
console.log(err);
})
//Promise的另一种写法
new Promise((resolve, reject) => {
setTimeout(() => {
// resolve('hello world');
reject('error message')
}, 1000)
}).then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
Promise的链式调用例子
// wrapped into
//网络请求:aaa -> 自己先处理(10行)然后拼接一个111
//处理:aaa111 -> 自己处理(10行) 然后拼接一个111
//处理aaa111222 -> 自己处理
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('aaa');
}, 1000)
}).then((res) => {
// 自己处理十行代码
console.log(res);
console.log(res, '第一层的十行处理代码');
// 2.对我们的结果进行第一次处理
//return new Promise((resolve) => {
// resolve(res + '111')
// })
//这里也可以写成
return Promise.resolve(res + '111')
//也可以
//return res+'111'
}).then((res) => {
console.log(res);
console.log(res, '第二层的十行处理代码');
// 3.对结果进行第二次处理
return new Promise((resolve) => {
resolve(res + '222');
})
}).then((res) => {
console.log(res);
console.log(res, '第三层的十行处理代码');
})
输出
aaa
aaa 第一层的十行处理代码
aaa111
aaa111 第二层的十行处理代码
aaa111222
04-Promise的链式调用(二).html:41 aaa111222 第三层的十行处理代码
Promise all
当我们现在有一种需求,即两种网络网络状态都满足进行下一步操作,这个时候就需要Promise all
Promise.all([
// new Promise((resolve, reject) => {
// $ajax({
// url: 'url1',
// success: function (data) {
// resolve(data);
// }
// })
// }),
// new Promise((resolve, reject) => {
// $ajax({
// url: 'url2',
// success: function (data) {
// resolve(data);
// }
// })
// })
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result1')
}, 2000)
}),
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('result2')
}, 1000)
})
]).then(results => {
console.log(results);
})
输出
(2) ["result1", "result2"]
0: "result1"
1: "result2"
length: 2
[[Prototype]]: Array(0)
Promise三种状态
- pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。
- fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then()
- reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()