详见:
JavaScript高级程序设计第四版学习记录-第十一章 期约与异步函数
第 11 章 期约与异步函数
本章内容
异步编程
期约 – Promise
异步函数 – 使用 async 和 await 关键字定义异步函数的机制
11.1 异步编程
11.1.1 理解异步函数&异步返回值
①
关键是理解为什么说它是一个异步函数。setTimeout 可以定义一个
在指定时间之后会被调度执行的回调函数。对这个例子而言,1000 毫秒之后,JavaScript 运行时会把回
调函数推到自己的消息队列上去等待执行。推到队列之后,回调什么时候出列被执行对 JavaScript 代码
就完全不可见了。还有一点,double()函数在 setTimeout 成功调度异步操作之后会立即退出。
function double(value) {
setTimeout(() => setTimeout(console.log, 0, value * 2), 1000);
}
double(3);
// 6(大约 1000 毫秒之后)
②异步返回值
假设setTimeout 操作会返回一个有用的值,把这个值传给需要它的地方 -> 策略:给异步操作提供一个回调
function double(value, callback) {
setTimeout(() => callback(value * 2), 1000);
}
double(3, (x) => console.log(`I was given: ${x}`));
// I was given: 6(大约 1000 毫秒之后)
2. 异步操作的成功回调&失败回调
function double(value, success, failure) {
setTimeout(() => {
try {
if (typeof value !== ‘number’) {
throw ‘Must provide number as first argument’;
}
success(2 * value);
} catch (e) {
failure(e);
}
}, 1000);
}
const successCallback = (x) => console.log(Success: ${x}
);
const failureCallback = (e) => console.log(Failure: ${e}
);
double(3, successCallback, failureCallback);
double(‘b’, successCallback, failureCallback);
// Success: 6(大约 1000 毫秒之后)
// Failure: Must provide number as first argument(大约 1000 毫秒之后)
这种模式已经不可取了,因为必须在初始化异步操作时定义回调。异步函数的返回值只在短时间内存在,只有预备好将这个短时间内存在的值作为参数的回调才能接收到它。
不是很明白,是指预备1000毫秒后才可以接收到的意思么????
11.1.3 嵌套异步回调
11.2 期约
1. 期约状态机
2. 通过执行函数
控制期约状态
控制期约状态的转换是通过调用它的两个函数参数实现的。这两个函数参数通常都命名为 resolve()
和reject()
。调用
resolve()会把状态切换为兑现,调用 reject()会把状态切换为拒绝。
执行器函数是同步执行的
new Promise(() => setTimeout(console.log, 0, 'executor'));
setTimeout(console.log, 0, 'promise initialized');
// executor
// promise initialized
添加 setTimeout 可以推迟切换状态:
let p = new Promise((resolve, reject) => {
setTimeout(resolve, 1000));
// 在 console.log 打印期约实例的时候,还不会执行超时回调(即 resolve()), setTimeout延迟1000ms
setTimeout(console.log, 0, p);
// Promise <pending>
}
3. Promise.resolve() & Promise.reject() – 可以实例化一个期约
①
下面两个期约实例实际上是一样的:
let p1 = new Promise((resolve, reject) => resolve());
let p2 = Promise.resolve();
②Promise.resolve()可以说是一个幂等
方法,
let p = Promise.resolve(7);
setTimeout(console.log, 0, p === Promise.resolve(p));
// true
setTimeout(console.log, 0, p === Promise.resolve(Promise.resolve(p)));
// true
这个幂等性会保留传入期约的状态:
let p = new Promise(() => {});
setTimeout(console.log, 0, p); // Promise <pending>
setTimeout(console.log, 0, Promise.resolve(p)); // Promise <pending>
setTimeout(console.log, 0, p === Promise.resolve(p)); // true
③Promise.reject()并没有照搬 Promise.resolve()的幂等逻辑
4. 同步/异步执行的二元性
5. 汇总