http.get('https://api.github.com/users', function(users) {
/* Display all users */
console.log(users);
http.get('https://api.github.com/repos/javascript/contributors?q=contributions&order=desc', function(contributors) {
/* Display all top contributors */
console.log(contributors);
http.get('https://api.github.com/users/Jhon', function(userData) {
/* Display user with username 'Jhon' */
console.log(userData);
});
});
});
从上面的代码片段中,你可以看到代码变得更加难以理解,以及难以维护和修改。这是由回调函数的嵌套而引发的。2 \9 J. F- i2 v. }! J/ m
八、如何避免回调地狱?7 @5 Y, k6 F' d8 d; f$ X
可以使用多种技术来避免回调地狱,如下所示。 ], }, i5 H& H2 v. S/ e+ N
使用promise
借助 async-await
使用 async.js 库) K. S. V0 P( d
使用 Async.js 库 1 m2 Y) y: w1 c6 ?9 m5 e 让我们谈谈怎样用 async.js 库避免回调地狱。根据 async.js 官方网站的描述:Async 是一个工具模块,它提供了直接、强大的函数来使用异步 JavaScript。& n* ?5 ~. M2 ^
Async.js 总共提供约 70 个函数。现在,我们将仅讨论其中两个,即 async.waterfall() 和 async.series()。: c# ] I `/ G! ~4 ? M
async.waterfall()! r: M( h+ }* I- a
当你要一个接一个地运行某些任务,然后将结果从上一个任务传到下一个任务时,这个函数非常有用。它需要一个函数“任务”数组和一个最终的“回调”函数,它会在“任务”数组中所有的函数完成后,或者用错误对象调用“回调”之后被调用。 O# \6 U* d9 e: n k( h1 d' |
var async = require('async');
async.waterfall([
function(callback) {
/*
Here, the first argument value is null, it indicates that
the next function will be executed from the array of functions.
If the value was true or any string then final callback function
will be executed, other remaining functions in the array
will not be executed.
*/
callback(null, 'one', 'two');
},
function(param1, param2, callback) {
// param1 now equals 'one' and param2 now equals 'two'
callback(null, 'three');
},
function(param1, callback) {
// param1 now equals 'three'
callback(null, 'done');
}
], function (err, result) {
/*
This is the final callback function.
result now equals 'done'
*/
});
async.series([
function(callback) {
// do some stuff ...
callback(null, 'one');
},
function(callback) {
// do some more stuff ...
callback(null, 'two');
}
],
// optional callback
function(err, results) {
// results is now equal to ['one', 'two']
});
九、Javascript 回调与闭包) J4 b+ W4 R3 t
闭包 + Q% w0 N' _) X# k 用技术术语来说,闭包是捆绑在一起的函数的组合,引用了其周围的状态。简而言之,闭包允许从内部函数访问外部函数的作用域。要使用闭包,我们需要在一个函数内部定义另一个函数。然后,我们需要将其返回或传给另一个函数。 - @) F' ~1 x T) e F回调 7 ^+ ~4 _; Y `2 J 从概念上讲,回调类似于闭包。回调基本上是把一个函数作为另一个函数的用法。