JavaScript 基础 / 第 4 课
异步操作与 Promise
用定时器观察异步执行顺序,再学习 Promise 和 async/await。
一般情况下,程序会按顺序执行语句。但有些操作需要等一会儿才完成;如果程序一直停下来等,后面的事情也会被耽误。JavaScript 可以先安排稍后执行的任务,再继续运行后面的语句,这种先继续、后处理结果的方式叫异步。
setTimeout 可以安排一段代码在指定毫秒数后运行。它用来演示等待,不需要访问网络或安装工具。看下面输出顺序:
console.log("开始");
setTimeout(function () {
console.log("稍后执行");
}, 500);
console.log("先继续");
会先显示“开始”和“先继续”,约半秒后才显示“稍后执行”。function () { ... } 是一个没有名字的小函数,这里把它交给 setTimeout,供定时器稍后调用。
传给定时器的数字单位是毫秒,500 毫秒是半秒。安排任务并不意味着程序暂停半秒;它只是登记一段稍后运行的代码。实际等待时间可能略长于设定值,因为当前执行的代码会先完成。这样可以区分“安排任务”和“任务真正运行”的时刻。
要表达“一个以后才会得到的结果”,可以用 Promise。它像一张结果凭据:刚创建时可能还在等待,之后会成功并带回值,也可能失败。then 注册成功时要做的事。下面的定时器模拟延迟后成功返回一个颜色:
const colorPromise = new Promise(function (resolve) {
setTimeout(function () {
resolve("紫色");
}, 500);
});
colorPromise.then(function (color) {
console.log(color);
});
resolve 表示操作成功,并把结果交给后续处理。async 函数可以使用 await 等待 Promise 成功结果,让相关步骤按阅读顺序排列;await 只能写在 async 函数里面。
调用 then 时,程序把处理函数登记到 Promise 上;结果准备好后才会用结果调用它。因此不要在创建 Promise 后马上假定值已经存在。await 会暂停当前 async 函数后续语句,等结果可用再继续,但不会让整个程序停下来。初学时可以把 await 理解成“在这个函数里等这个结果”。
async function showColor() {
const color = await colorPromise;
console.log(color);
}
showColor();
练习:用 setTimeout 延迟 300 毫秒显示 "完成",并在安排定时器后立刻显示 "等待中"。
答案:
setTimeout(function () {
console.log("完成");
}, 300);
console.log("等待中");
此处展示成功的情况。Promise 失败时也能记录错误,暂时先掌握等待并取得成功结果的路径。
互动练习:等待异步结果
在 async 函数里,哪种写法会等待 Promise 完成后再取得结果?
理解异步等待、Promise 状态与 async/await 写法