Promise是ES6的一个用于处理异步操作的库。他本身是没有异步功能的,只是更方便异步操作而已。如果你用过类似rxjava的库的话,你就很容易明白。不过比rxjava简单的多。没用过也没关系。
在前端应用种,我们经常需要发送网络请求。有可能通过一个url请求到另一个url,在通过这个url请求到第三个url。可能嵌套个4 5层。例如下面的代码,这样的代码是非常难以维护的。Promise就可以专门用来处理这种问题。
$ajax{
//100行逻辑处理
$ajax{
//100行逻辑处理
$ajax{
//100行逻辑处理
$ajax{
//100行逻辑处理
$ajax{
//100行逻辑处理
}
}
}
}
}
我们先写一个嵌套的例子。然后用Promise进行改造。
下面这个代码就是所谓的回调地狱。如果代码很多,那么将非常的混乱。
setTimeout(()=>{
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
setTimeout(()=>{
console.log("Hello JS")
console.log("Hello JS")
console.log("Hello JS")
console.log("Hello JS")
console.log("Hello JS")
setTimeout(()=>{
console.log("Hello Python")
console.log("Hello Python")
console.log("Hello Python")
console.log("Hello Python")
console.log("Hello Python")
},1000)
},1000)
},1000)
我们用Promise就可以写成下面的代码。
这代码怎么还变多了?代码多少不是关键,关键是代码结构变得清晰了。而且变成了链式编程。也就是嵌套的问题没有了,现在所以的代码都处在同一级上,至少从结构上来说是这样。
代码多不是问题,后面介绍简写的写法。简写之后只能用一个词形容,就是优雅。后面介绍。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
}).then(() => {
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
})
}).then(() => {
console.log("Hello JS")
console.log("Hello JS")
console.log("Hello JS")
console.log("Hello JS")
console.log("Hello JS")
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, 1000)
})
}).then(() => {
console.log("Hello Python")
console.log("Hello Python")
console.log("Hello Python")
console.log("Hello Python")
console.log("Hello Python")
})
请求失败的情况,如果请求失败,可以调用reject方法,并且在catch处理错误。后面的操作都会中断。
new Promise((resolve, reject) => {
setTimeout(() => {
// resolve()
reject("err message")
}, 1000)
}).then(() => {
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
}).catch((err)=>{
console.log(err);
})
还有一种处理错误的方式是使用then的第二个参数,可以直接处理错误的情况。
new Promise((resolve, reject) => {
setTimeout(() => {
// resolve()
reject("err message")
}, 1000)
}).then(() => {
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
console.log("Hello World")
}, err => {
console.log(err);
})
还可以使用Promise进行任务方便,分步操作。
//使用Promise进行多次处理,任务分解。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("aaa")
}, 1000)
}).then(res => {
console.log("第一次10行处理")
return new Promise(resolve => {
//对结果进行第一次处理
resolve(res+"111")
})
}).then(res=>{
console.log("第二次10行处理")
return new Promise(resolve => {
//对结果进行第一次处理
resolve(res+"222")
})
}).then(res=>{
console.log("第三次10行处理")
return new Promise(resolve => {
//对结果进行第一次处理
resolve(res+"333")
})
})
上面的写法可以简写成下面的样子,代码少了很多。
//使用Promise进行多次处理,任务分解。
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("aaa")
}, 1000)
}).then(res => {
console.log("第一次10行处理")
return Promise.resolve(res + "111")
}).then(res => {
console.log("第二次10行处理")
return Promise.resolve(res + "222")
}).then(res => {
console.log("第三次10行处理")
return Promise.resolve(res + "333")
})
处理错误的简写形式。
//还能进一步简写,Promise都不想写,这样已经非常舒服了
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("aaa")
}, 1000)
}).then(res => {
console.log("第一次10行处理")
return res + "111"
}).then(res => {
console.log("第二次10行处理")
return Promise.reject("err message")
}).then(res => {
console.log("第三次10行处理")
return res + "333"
}).catch(err=>{
console.log("err message from second process")
})
有这样的需求,在两个请求都返回结果后,发生第三个请求。关键点就是我们怎么监听到前面两个请求什么时候结束。
Promise为我们提供了all方法来处理这个问题。
也是非常的简洁好用。
Promise.all([
new Promise((resolve, reject) => {
setTimeout(()=>{
console.log("开始第一个请求")
resolve("result1")
},2000)
}),
new Promise((resolve, reject) => {
setTimeout(()=>{
console.log("开始第二个请求")
resolve("result2")
},1000)
})
]).then(results=>{
console.log(results[0])
console.log(results[1])
console.log("开始第三个请求")
})