Promise理解


Promise 理解

Promise 是什么?

  1. 抽象表达
  • Promise 是一门新的技术(ES6 规范)
  • Promise 是 JS 中进行异步编程的新解决方案(旧方案单纯使用回调函数)
  1. 具体表达
  • 从语法上看,Promise 是一个构造函数
  • 从功能上看,Promise 对象是一个用来封装一个异步操作并可以获取其成功/失败的结果值

Promise 的状态改变

  1. pendding 变为 resolved
  2. pendding 变为 rejected

说明:

  • 只有这 2 种,且一个 promise 对象只能改变一次
  • 无论变为成功还是失败,都会有一个结果数据
  • 成功的结果数据一般称为 value,失败的结果数据一般称为 reason

Promise 基本流程

avatar

Promise 基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//1.创建一个Promise对象
let promise = new Promise((resolve, reject) => {
//执行器函数,同步回调
let time = new Date();
setTimeout(function () {
if (time % 2) {
resolve("promise成功状态" + time);
} else {
reject("promise失败时间" + time);
}
}, 1000);
});
promise.then(
//接收得到成功的value值
(value) => {
console.log(value);
},
(reason) => {
console.log(reason);
}
);

使用 Promise 的原因

(一)、Promise 方式指定回调函数的方式更加灵活

  1. 纯异步任务
  • 其回调函数需要提前指定,在启动异步任务之前就要指定;
  • 回调函数必须再启动异步任务之前指定
  1. Promise 方式

启动异步任务=>返回 promise 对象=>给 promise 对象绑定回调函数(甚至可以再异步任务之后)

  • ① 先启动执行器函数,执行器函数执行启动后才得到一个 promise 对象;
  • ② 执行器函数启动,则异步任务启动,异步任务处理过程中,未完成;
  • ③ 回调函数可以随后指定,无需提前指定;

(二)、Promise 支持链式调用,可以解决回调地狱问题

回调地狱:回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件

解决方案:promise 链式调用

async/await:回调地狱的终极解决方案

1
2
3
4
5
6
7
8
9
10
async function request() {
try {
const result = await doSomething();
const newResult = await doSomethingElse();
const finalResult = await doThirdThing();
console.log(finalResult);
} catch (error) {
failureCallback(error);
}
}

如何使用 Promise

API

  1. Promise 构造函数:Promise(excutor){}

    • excutor 函数:同步执行 (resolve,reject)=>{}
    • resolve 函数:内部定义成功时我们调用的函数 value=>{}
    • reject 函数:内部定义失败时我们调用的函数 reason=>{}
  2. Promise.prototype.then 方法:(onResolved,onRejected)=>{}

    • onResolved 函数:成功的回调函数(value)=>{}

    • onRejected 函数:失败的回调函数(reason)=>{}

      说明:指定用于得到成功 value 的成功回调和用于得到失败 reason 的失败回调,返回一个新的 promise 对象

  3. Promise.prototype.catch 方法:(onRejected)=>{}

    • onRejected 函数:失败的回调函数(reason)=>{}

      说明:then()语法糖,相当于:then(undefined,onRejected)

  4. Promise.resolve 方法:(value)=>{}

    • value:成功的数据或 promise 对象

      说明:resolve 方法返回一个成功/失败的 promise 对象

  5. Promise.reject 方法:(reason)=>{}

    • reason:失败的原因

    说明:返回一个失败的 promise 对象

  6. Promise.all 方法:(promise)=>{}

    • promises:包含 n 个 promise 数组

      说明:返回一个新的 promise,只有所有的 promise 都成功才成功,只要有一个失败了就直接失败

  7. Promise.race 方法:(promise)=>{}

    • promises:包含 n 个 promise 的数组

      说明:返回一个新的 promise,最先完成的 promise 的结果状态就是最终的结果状态

Promise 几个关键问题

  1. 如何改变 promise 的状态
  • ① resolve(value):如果当前时 pendding 就会变成 resolved
  • ② reject(reason):如果当前时 pendding 就会变成 rejected
  • ③ 抛出异常:如果当前时 pendding 就会变成 rejected
  1. 一个 promise 指定多个成功/失败回调函数,都会调用?
  • 当 promise 改变为对应状态时都会调用
  1. 改变 promise 状态和指定回调函数谁先谁后?
  • (1)都有可能,正常情况下时先指定回调再改变状态,但也可以先改变状态再指定回调

  • (2)如何先改变状态再指定回调?

    • ① 在执行器中直接调用 resolve()/reject()
    • ② 延迟更长时间才调用 then
  • (3)什么时候才能得到数据?

    • ① 如果先指定的回调,那当状态改变时,回调函数就会调用,得到数据
1
2
3
4
5
6
7
8
9
10
11
12
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("123");//后改变状态(同时指定数据),异步执行回调函数
}, 1000);
}).then(
(value) => {//先指定回调函数,保存当前指定的回调函数
console.log("先指定回调函数");
},
(reason) => {
console.log(reason);
}
);
  • ② 如果先改变的状态,那当指定回调时,回调函数就会调用,得到数据
1
2
3
4
5
6
7
8
9
10
11
new Promise((resolve, reject) => {
resolve("123"); //先改变的状态(同时指定数据)
}).then(
(value) => {
//后指定回调函数,异步执行回调函数
console.log("123");
},
(reason) => {
console.log(reason);
}
);
  1. promise.then()返回的 promise 的结果状态由什么决定?
  • (1)简单表达式:由 then()指定的回调函数执行的结果决定
  • (2)详细表达:
    • ① then()指定的回调函数执行的结果抛出异常,新 promise(then 方法返回的 promise)变为 rejected,reason 为抛出的异常;
    • ② then()指定的回调函数执行的结果返回的是非 promise 的任意值,新 promise 变为 resolved,value 为返回的值
    • ③ then()指定的回调函数执行的结果返回的是另一个新的 promise,此 promise 的结果将会成为新 promise 的结果
  1. promise 如何串联多个操作任务?
  • (1)promise 的 then()返回一个新的 promise,可以看成 then()的链式调用
  • (2)通过 then 的链式调用串联多个同步/异步任务
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
new Promise((resolve, reject) => {
setTimeout(() => {
console.log("执行任务1(异步)");
resolve(1);
}, 1000);
})
.then((value) => {
console.log("任务1结果:" + value);
console.log("执行任务2(同步)");
return 2; //返回一个常量,(同步返回直接return就行)决定then返回的promise为成功状态,值为2
})
.then((value) => {
console.log("任务2的结果" + value);
return new Promise((resolve, reject) => {
//异步操作则要由promise封装
setTimeout(() => {
console.log("执行任务3(异步)");
resolve(3);
// console.log("111");
// return 3; //下一个then不会输出,不是当前then方法的return,那就运行到此,下一个then也不会执行
// console.log("222");
}, 1000);
// console.log("333");
});

//不行,异步应该包含在一个promise对象中才能传递下去
//这样就不能按顺序输出,则return的值不能被后续then接收到则会出现undefined
/**
* 执行任务1(异步)
任务1结果:1
执行任务2(同步)
任务2的结果2
任务3结果undefined
执行任务4
任务4结果undefined
执行任务3(异步)
*/
// setTimeout(() => {
// console.log("执行任务3(异步)");
// return 3;
// }, 1000);
})
.then((value) => {
console.log("任务3结果" + value);
console.log("执行任务4");
return Promise.resolve(4)

// console.log(p);
})
.then((value) => {
console.log("任务4结果" + value); //任务4结果undefined
});
  1. promise 异常穿透
  • then 返回的 promise 失败的情况:① 抛异常 ② 返回失败的 promise
  • 异常一层层传递下去到 catch
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
30
new Promise((resolve, reject) => {
// resolve(1);
reject(1);
})
.then((value) => {
console.log("任务1结果:" + value);
console.log("执行任务2");
return 2;
})
.then(
(value) => {
console.log("任务2的结果" + value);
return 3;
}
// (reason) => {
// throw error;
// }
)
.then(
(value) => {
console.log("任务3结果" + value);
}
// (reason) => {
// throw error;
// }
)
.catch((reason) => {
console.log("执行错误:" + reason);
});

  • (1)当使用 promise 的 then 链式调用时,可以在最后指定失败的问题
  • (2)前面任何操作出了异常,都会传到最后失败的回调中
  1. 中断 promise 链?
  • (1)当使用 promise 的 then 链式调用时,在中间中断,不再调用后面的回调函数
  • (2)办法:在回调函数中返回一个 pendding 状态的 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) => {
// resolve(1);
reject(1);
})
.then((value) => {
console.log("任务1结果:" + value);
console.log("执行任务2");
return 2;
})
.catch((reason) => {
console.log("执行错误:" + reason);
/**
* 未中断
* return 2; //返回下一个then的value
* return Promise.reject(2); //进入下一个then的reason
*/
/**
* 中断情况
*/
return new Promise(() => {}); //返回一个pendding的promise,中断promise链
})
.then(
(value) => {
console.log(value);
},
(reason) => {
console.log(reason);
}
);

文章作者: AlfaLee
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 AlfaLee !
  目录