在js中,如果函数B需要A的返回值,由于js的异步执行,我们会得到一个undefined,本文通过代码实例记录了js异步编程的4中解决方案。
问题实例
函数A比较耗时,但是函数B需要函数A的返回结果,如果按我们正常的写法,应该是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13
| var self = this; function A (arg) { setTimeout(function () { self.numA = 3 * arg; console.log("A的值是" + self.numA); }, 500); } function B () { var numB = self.numA * 4; console.log("B的值是" + numB); } A(2); B(3);
|
但是执行结果确实这样的
如果我们使用嵌套的方法,代码是横向扩展,很不美观,且不易阅读。有以下几种解决方案。
方案一:回调函数
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| var self = this; function A (arg, callback) { setTimeout(function () { self.numA = 3 * arg; console.log("A的值是" + self.numA); callback(); }, 1000); } function B () { var numB = self.numA * 4; console.log("B的值是" + numB); } A(2, B);
|
输出结果如下:
是我们的期望结果
如果你想在函数A执行完setTimeout之后再执行函数B,那么通过回调函数是无法事项的。可以通过下面的方法实现。
方案二:Promises对象
还是按照上面的顺序,函数A需要在B前面执行。Promises对象的大致意思是没执行一个异步任务就返回一个promise对象,对象有then方法,允许有回调函数,可以这样写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var self = this; function A() { return new Promise(function (resolve, reject) { setTimeout(function () { self.numA = 3; console.log("A的值是" + self.numA); resolve('Async Hello world'); }, 500); }); } A().then(function (value) { var numB = self.numA * 4; console.log("B的值是" + numB); console.log(value); }).catch(function (error) { console.log(error); });
|
Promise 的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。在不同的js框架中使用会有所差别。
其他
除了以上两种方法,我们还可以通过事件的监听、发布/订阅等方法实现异步编程,但是不同的框架实现方法可能会有所差别。但是,作为一个初学者,我们应该抱着学习的心态使用回调函数,有助于理解js。
参考文献:
- Javascript异步编程的4种方法
- JavaScript Promise迷你书(中文版)
最后更新时间: