今天研究一个小问题: 怎么拿到 JavaScript 异步函数的返回值?
1. 错误尝试
当年未入行时, 我的最初尝试:
html 代码
- <script>
- function getSomething() {
- var r = 0;
- setTimeout(function() {
- r = 2;
- }, 10);
- return r;
- }
- function compute() {
- var x = getSomething();
- alert(x * 2);
- }
- compute();
- </script>
2. 回调函数
弹出的不是 4, 而是 0, 后来知道这是异步的问题,
要用回调技术来做:
HTML 代码
- <script>
- function getSomething(cb) {
- var r = 0;
- setTimeout(function() {
- r = 2;
- cb(r);
- }, 10);
- }
- function compute(x) {
- alert(x * 2);
- }
- getSomething(compute);
- </script>
- 3.promise
回调函数真是个好东西, 然后一直这么写代码写了很久.
遇到异步就传函数!!
后来我知道有 promise 这一个东西,
专门解决由于回调函数引起的问题, 又学会了 promise:
HTML 代码
- <script>
- function getSomething() {
- var r = 0;
- return new Promise(function(resolve) {
- setTimeout(function() {
- r = 2;
- resolve(r);
- }, 10);
- });
- }
- function compute(x) {
- alert(x * 2);
- }
- getSomething().then(compute);
- </script>
promise 仍然没有放弃回调,
只是回调的位置发生了改变.
4.generator
再后来我又学会了 generator,
知道其有中断函数执行的能力,
又做了新的尝试:
HTML 代码
- <script>
- function getSomething() {
- var r = 0;
- setTimeout(function() {
- r = 2;
- it.next(r);
- }, 10);
- }
- function *compute() {
- var x = yield getSomething();
- alert(x * 2);
- }
- var it = compute();
- it.next();
- </script>
同步的写法, 能实现异步的逻辑, 感觉高大上了很多.
5.promise + generator
后来又听说 promise 加 generator, 才是异步的完美方式,
赶紧用高射炮打蚊子 (这个例子, 还不足以说出二者在一起用的好处):
HTML 代码
- <script>
- function getSomething() {
- var r = 0;
- return new Promise(function(resolve) {
- setTimeout(function() {
- r = 2;
- resolve(r);
- }, 10);
- });
- }
- function *compute() {
- var x = yield getSomething();
- alert(x * 2);
- }
- var it = compute();
- it.next().value.then(function(value) {
- it.next(value);
- });
- </script>
- 6.async
心想这算是够屌的吧, 后来又听说 es7 给出了终极方案: async.
作为爱学习的少年, 心想自己不能被落下:
HTML 代码
- <script>
- function getSomething() {
- var r = 0;
- return new Promise(function(resolve) {
- setTimeout(function() {
- r = 2;
- resolve(r);
- }, 10);
- });
- }
- async function compute() {
- var x = await getSomething();
- alert(x * 2);
- }
- compute();
- </script>
到这里终于长出了一口气.
后记:
上面所有的例子, 在最新 Chrome 上都可以运行.
一个个小例子, 点了点几个名词.
当然也只是 "点" 而已, 如果能提供读者深入学习相关知识点的一个 trigger, 那么老姚就心满意足了.
参考资料:
《你不知道的 JavaScript 中卷》
《ECMAScript 6 入门》阮一峰
本文完.
来源: http://www.qdfuns.com/article/17398/8a2084587fbd3f6c170c1bb8a79045c6.html