- 11.1 异步编程
异步行为是为了优化因计算量大而时间长的操作。如果在等待其他操作完成的同时,即使运行其他指令,系统也能保持稳定.量大或要等很长时间。你不想为等待某个异步操作而阻塞线
程执行,那么任何时候都可以使用。
- 同步与异步
同步行为每条指令都会严格按照它们出现的顺序来执行
如果代码要访问一些高延迟的资源,比如向远程服务器发送请求并等待响应,那么就会出现长时间的等待。
异步操作的例子可以是在定时回调中执行一次简单的数学计算:let x = 3; setTimeout(() => x = x + 4, 1000);
这段程序最终与同步代码执行的任务一样,都是把两个数加在一起,但这一次执行线程不知道 x 值何时会改变,因为这取决于回调何时从消息队列出列并执行 - 11.2 期约promise
ECMAScript 6 新增的引用类型 Promise ,可以通过 new 操作符来实例化。创建新期约时需要传入执行器(executor)函数作为参数let p = new Promise(() => {}); setTimeout(console.log, 0, p); // Promise <pending>
在把一个期约实例传给 console.log() 时,控制台输出(可能因浏览器不同而略有差异)表明该
实例处于待定(pending)状态。如前所述,期约是一个有状态的对象,有三种状态
待定(pending)
兑现(fulfilled,有时候也称为“解决”,resolved)
拒绝(rejected)
期约主要有两大用途。首先是抽象地表示一个异步操作。期约的状态代表期约是否完成。“待定”表示尚未开始或者正在执行中。“兑现”表示已经成功完成,而“拒绝”则表示没有成功完成。
比如,假设期约要向服务器发送一个 HTTP 请求。请求返回 200~299 范围内的
状态码就足以让期约的状态变为“兑现”。类似地,如果请求返回的状态码不在 200~299 这个范围内,那么就会把期约状态切换为“拒绝”。
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
控制期约状态的转换是通过调用它的两个函数参数实现的。这两个函数参数通常都命名为 resolve() 和 reject()
let p1 = new Promise((resolve, reject) => resolve());
setTimeout(console.log, 0, p1); // Promise <resolved>
let p2 = new Promise((resolve, reject) => reject());
setTimeout(console.log, 0, p2); // Promise <rejected>
// Uncaught error (in promise)
- 在 ECMAScript 暴露的异步结构中,任何对象都有一个 then() 方法
把期约逐个地串联起来是一种非常有用的编程模式。之所以可以这样做,是因为每个期约实例的方法( then() 、 catch() 和 finally() )都会返回一个新的期约对象,而这个新期约又有自己的实例方法。这样连缀方法调用就可以构成所谓的“期约连锁”。比如:let p = new Promise((resolve, reject) => { console.log('first'); resolve(); }); p.then(() => console.log('second')) .then(() => console.log('third')) .then(() => console.log('fourth')); // first // second // third // fourth