什么是 Promise 呢?

ES6中一个非常重要和好用的特性就是 Promise

Promise 是异步编程的一种解决方案



处理异步

在封装一个网络请求的函数,如果网络请求非常复杂,就会出现回调地狱

示例

上面的代码,可以正常运行并且获取我们想要的结果,但是当每次处理传递的数据进行几百行代码,然后再进行回调。代码丑陋且不易维护。使用Promise可以优雅的解决这个问题

使用Promise写一个简单的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
new Promise((resolve,reject) =>{
setTimeout( () =>{
resolve('Hello World')
reject('Error Data')
},1000)
}).then(data =>{
console.log(data)
}).catch(error =>{
console.log(error)
})

// 另一种写法
new Promise((resolve,reject) =>{
setTimeout( () =>{
resolve('Hello World')
reject('Error Data')
},1000)
}).then(data =>{
console.log(data)
}, err =>{
console.log(err)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
new Promise((resolve,reject) =>{
setTimeout( () =>{
resolve('Hello World')
reject('Error Data')
},1000)
}).then(data =>{
console.log(date)

return new Promise((resolve,reject) =>{
setTimeout( () =>{
resolve('Hello World')
reject('Error Data')
},1000)
})
}).then()

Promise 三种状态

  1. pending 等待状态,比如正在进行网络请求,或者定时器没有到时间
  2. fulfill 满足状态,当我们主动回调了 resolve ,就处于该状态,并且会回调.then()
  3. reject 拒绝状态,当我们主动回调了 reject,就处于该状态,并且会回调.catch()

Promise 链式调用

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
new Promise((resolve,reject) =>{
// 第一次网络请求
setTimeout(() =>{
resolve()
},1000)
}).then(()=>{
// 第一次拿到结果的处理代码
console.log('第一次')

return new Promise((resolve,reject) =>{
// 第二次网络请求
setTimeout(()=>{
resolve()
},1000)
})
}).then(()=>{
// 第二次拿到结果
console.log('第二次')

return new Promise((resolve,reject) =>{
// 第三次网络请求
setTimeout(()=>{
resolve()
},1000)
})
}).then(()=>{
// 第三次拿到结果
console.log('第三次')
})

链式调用的另一种写法

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
// 网络请求:aaa -> 自己处理(10)行
// 处理:aaa111 -> 自己处理(10)行
// 处理:aaa111222 -> 自己处理(10)行
new Promise((resolve,reject) =>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
// 1.自己处理10行代码
console.log(res,'第一层的10行处理代码')

// 2.对结果进行第一次处理
// reject参数是可选的,后面均可不写
return new Promise((resolve)=>{
resolve(res + '111')
})
}).then(res =>{
// 1.自己处理10行代码
console.log(res,'第二层的10行处理代码')

// 2.对结果进行第二次处理
return new Promise((resolve)=>{
resolve(res + '222')
})
}).then(res =>{
console.log(res,'第三层的10行处理代码')
})

简写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
new Promise((resolve,reject) =>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
// 1.自己处理10行代码
console.log(res,'第一层的10行处理代码')

// 2.对结果进行第一次处理
// reject参数是可选的,后面均可不写
return Promise.resolve(res + '111')
})
}).then(res =>{
// 1.自己处理10行代码
console.log(res,'第二层的10行处理代码')

// 2.对结果进行第二次处理
return Promise.resolve(res + '222')
})
}).then(res =>{
console.log(res,'第三层的10行处理代码')
})

再次简写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 省略Promise.resolve,内部会使用promise包装
new Promise((resolve,reject) =>{
setTimeout(()=>{
resolve('aaa')
},1000)
}).then(res=>{
// 1.自己处理10行代码
console.log(res,'第一层的10行处理代码')

// 2.对结果进行第一次处理
// reject参数是可选的,后面均可不写
return res + '111'
}).then(res =>{
// 1.自己处理10行代码
console.log(res,'第二层的10行处理代码')

// 2.对结果进行第二次处理
return res + '222'
}).then(res =>{
console.log(res,'第三层的10行处理代码')
})

某层调用了reject

1
2
3
4
5
6
	return Promise.reject('error message')
}).catch(error=>{
console.log(error)
})
// 直接执行catch操作,后面的then是跳过

抛出异常

1
2
3
4
5
	throw 'error message'
}).catch(error=>{
console.log(error)
})
// 仍然可以捕获到异常

Promise的all方法使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Promise.all([
new Promise((resolve,reject) =>{
$.ajax({
url:'url1'
success: function(data){
resolve(data)
}
}),
$.ajax({
url:'url2'
success: function(data){
resolve(data)
}
})
})
]).then(results=>{
// results是数组,用于存放上面两个网络请求的结果,results[0]是第一个
console.log(results)
})