用 JavaScript 语言写的应用里会有一些异步(Asynchronous)的动作,就是执行这些动作的时候不能马上得到结果,这个动作需要点时间。处理应用里的这些异步的行为有几种方法,比如可以使用回调函数(Callback),可以使用 Promise,也可以用 async 函数。
Callback
定义一个函数的时候可以让这个函数支持使用一个函数参数,这个函数参数就是 Callback,也就是回调。使用这个函数的时候可以给它提供一个函数参数,也可以说给它一个 “回调”。
示例:
const nature = callback => { const data = '🌳'; callback(data); };
上面用箭头函数的形式定义了一个叫 nature()
的函数,这个函数支持一个 callback
参数,这个参数应该是个函数,这里我叫它 callback
,其实任何名字都是可以的。在 nature()
函数的内部执行了一下它的 callback
这个函数参数,执行的时候给它提供了一个 data
参数,这个 data
就是这个回调函数的参数。
nature(data => { console.log(data); }); // 在控制台上会输出 -> 🌳
在使用 nature()
这个函数的时候,我们可以给它提供一个函数参数,也就是给它提供一个回调函数,这个回调支持一个参数,这个参数就是 data
,当然你在这个回调里可以任意修改这个参数的名字。在这个回调函数的内部我们可以利用这个 data
参数去做一些事情,这里就是在控制台输出了这个 data
的值。所以这里执行这个 nature()
函数的结果就是在控制台上输出了一个:🌳
Promise
在应用里做的事情很多时候我们不能立即拿到结果,比如让应用从数据仓库里调取一组数据,这需要花点时间,应用向数据仓库发出指令调取数据,数据仓库服务要处理一下,完成以后才能把应用需要的数据交给应用。再比如在应用里需要请求一个外部服务接口,要等待外部接口发回来的响应的结果。如果同步执行这些动作,应用会卡住,等待处理的结果,拿到结果以后才能去做其它的事情。或者我们也可以异步完成这些事情,这样应用可以继续去做其它的事情。
Promise 就是在 JavaScript 语言里提供的一些处理异步动作的方法。比如你想异步完成一些事情,可以制造一个 Promise。就是你让应用去做一些事情,因为不能马上得到结果,所以只能先拿到一个承诺,这个承诺在未来可能会被兑现,也可能被拒绝。我们可以事先设计好当承诺兑现的时候要做什么,在承诺被拒绝以后要做什么。
示例:
const nature = () => { return new Promise((resolve, reject) => { resolve('🦖'); }); };
上面定义了一个叫 nature()
的函数,这个函数里面会制造返回一个 Promise。在制造这个 Promise 的时候给它提供一个函数参数,这个函数参数可以有两个参数,resolve
还有 reject
。它们两个是回调函数,成功兑现就执行 resolve()
带着结果,失败就在这个 Promise 里执行 reject()
带着错误。
在这个给 Promise 提供的函数参数的内部,可以去做一些异步的动作,比如去调取数据仓库里的数据,请求外部服务接口等等。当成功完成了这些事情以后,就可以执行一下 resolve()
这个函数,把结果交给这个 resolve()
。为了减少干扰,这里我们直接把一只 🦖 交给 resolve()
,这只 🦖 就是这个 Promise 最终产生的数据。
nature()
这个函数会返回一个 Promise ,执行这个函数的时候可以这样做:
nature().then(data => { console.log(data); }); // 在控制台上会输出 -> 🦖
先执行 nature()
函数,接着再用一个 .then()
,在这个函数里可以设计一下当承诺成功兑现之后要做的事情,给这个 .then()
提供一个回调参数,这个回调支持一个 data
参数,这里这个 data
就是 Promise 最终生产出来的数据,也就是在 Promise 里面,交给 resolve()
函数的值。
模拟异步动作
如果你想模拟一下异步动作,可以使用 setTimeout()
,它可以设置在规定的时间结束以后再执行指定的动作。
示例:
const nature = () => { console.log('...'); return new Promise((resolve, reject) => { setTimeout(() => { resolve('🦖'); }, 2000); }); }; nature().then(data => { console.log(data); }); console.log('🌋'); // 在控制台上会输出: ... 🌋 🦖
async 函数
用 async 关键词可以定义异步函数,这种异步函数可以简化 Promise 的使用。
示例:
const demo = async () => { const data = await nature(); console.log(data); }; demo(); // 在控制台上会输出: ... 🦖
定义 demo()
这个函数的时候用了 async
这个关键词,这样它就会是一个异步函数,在函数里面可以使用 await
这个关键词等待执行异步动作。比如我们在 demo()
这个函数里,执行 nature()
函数的前面,用了 await
,这个 nature()
就是在练习 Promise 的时候创建的一个函数,函数会返回一个 Promise,所以可以在它的前面用 await
,等这个 Promise 最终生产出来数据以后,把这个数据交给 data
,在 demo()
函数里,我们可以利用这个 data
的值,比如在控制台上输出它。