Promise
前言
1、Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有执行了resolve()或reject(),才能决定当前是哪一种状态。
2、Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。假如没有调用resolve()或reject(),状态会一直是pending,但是不影响后面的js。
3、resolve和reject只能传一个参数
Promise优缺点
1、优点:可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
2、缺点:1. 无法取消Promise,一旦新建它就会立即执行,无法中途取消。2. 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。3. 当处于pending状态时,无法得知目前进展到哪一个阶段
new Promise
1、new Promise 时要传入函数,函数有resolve reject 两个参数。
1 | let promise2 = new Promise(function(resolve, reject){ |
Promise实用写法
因为Promise新建后就会立即执行里面的函数,所以一般都是定义方法1
2
3
4
5
6
7
8
9function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
})catch(val => {console.log('error')}) // 不要用then(resolve, reject)方法,采用链式方法
Promise注意点
Promise新建后就立即执行,但是resolve和reject却是异步后执行的,所以等当前脚本所有同步任务完成后才会执行。只有当Promise内部语法错误的时候才会停止下面的脚本,所以只要语法没有错误,都会执行完所有脚本才执行resolve和reject。1
2
3
4
5
6
7
8
9
10
11
12
13let promise = new Promise(function(resolve, reject) {
console.log('Promise');
resolve();
console.log('后面的内容')
});
promise.then(function() {
console.log('resolved.');
}).catch() // 每个new Promise都要有catch,不然Promise内部有语法错误,不会终止下面js的运行
console.log('Hi!');
// Promise
// '后面的内容'
// Hi!
// resolved
// resolve和reject()只能支持传一个实参
new Promise((resolve, reject) => {
resolve(1,2)
}).then((a,b) => {console.log(a, b)}) // 1, undefined
Promise加载图片实例
1 | function loadImageAsync(url) { |
Promise实现Ajax实例
1 | const getJSON = function(url) { |
Promise.prototype.then()和Promise.prototype.catch()
then/catch方法返回的是一个新的Promise实例,所以可以链式调用,有时候还需要它执行new Promise定义的方法,这时候只要返回之前的new Promise的函数就行了1
2
3
4
5
6
7getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL); // 返回时新的Promise对象,所以还是需要执行new Promise,然后根据状态调用方法
}).then(function funcA(comments) {
console.log("resolved: ", comments);
}, function funcB(err){
console.log("rejected: ", err);
});
1 | // 以下2个写法是一样的 |
Promise.prototype.finally
不管Promise状态是正确还是错误,都会执行finally1
2
3
4promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
Promise.all
Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。Promise.all接受一个promise对象的数组,待全部完成之后,统一执行success;1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23const p = Promise.all([p1, p2, p3]);
// p的状态由p1、p2、p3决定,分成两种情况。
// 1、只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
// 2、只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
// 生成一个Promise对象的数组
let fn = function(val){
return new Promise(function(resolve, reject){
setTimeout((val) => {
console.log(String(val).repeat(3), val);
resolve(val)
}, Number(val)*1000, val)
return val
})
}
let arr = [1,2,3,4,5].map((item) =>{return fn(item)})
Promise.all(arr).then(val => {console.log(val)})
// 111 1
// 222 2
// 333 3
// 444 4
// 555 5
// [1,2,3,4,5]
Promise.prototype.race
Promise.race接受一个包含多个promise对象的数组,只要有一个完成,就执行success
Asnc/Await
前言
async/await是写异步代码的新方式,基于Promise实现的,但是优于回调函数和Promise。函数不能阻塞后面脚本运行,只有函数里的才会等待。
用法
1、使用await,函数必须用async标识。2、await后面跟的是一个Promise实例。3、需要安装babel-polyfill,安装后记得引入 //npm i –save-dev babel-polyfill
1 | function loadImg(src) { |
捕获错误
1 | async function myFunction() { |
为什么Async/Await更好
1、不需要写.then,不需要写匿名函数处理Promise的resolve值,也不需要定义多余的data变量,还避免了嵌套代码。
2、可能遇到过这样的场景,调用promise1,使用promise1返回的结果去调用promise2,然后使用两者的结果去调用promise3。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17// promise
const makeRequest = () => {
return promise1()
.then(value1 => {
return promise2(value1)
.then(value2 => {
return promise3(value1, value2)
})
})
}
// 使用async/await
const makeRequest = async () => {
const value1 = await promise1()
const value2 = await promise2(value1)
return promise3(value1, value2)
}
3、条件判断更直观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// promise
const makeRequest = () => {
return getJSON()
.then(data => {
if (data.needsAnotherRequest) {
return makeAnotherRequest(data)
.then(moreData => {
console.log(moreData)
return moreData
})
} else {
console.log(data)
return data
}
})
}
// async/await
const makeRequest = async () => {
const data = await getJSON()
if (data.needsAnotherRequest) {
const moreData = await makeAnotherRequest(data);
console.log(moreData)
return moreData
} else {
console.log(data)
return data
}
}