JavaScript中的回调地狱及解决方法
1、回调地狱
在使用JavaScript时,为了实现某些逻辑经常会写出层层嵌套的回调函数,如果嵌套过多,会极大影响代码可读性和逻辑,这种情况也被成为回调地狱。比如说你要把一个函数 A 作为回调函数,但是该函数又接受一个函数 B 作为参数,甚至 B 还接受 C 作为参数使用,就这样层层嵌套,人称之为回调地狱,代码阅读性非常差。比如:
var sayhello = function (name, callback) { setTimeout(function () { console.log(name); callback(); }, 1000); } sayhello("first", function () { sayhello("second", function () { sayhello("third", function () { console.log("end"); }); }); }); //输出: first second third end
2、解决回调地狱
解决回调地狱有很多方法,比如:Promise 对象、Generator 函数、async 函数
3、Promise 对象解决回调地狱
采用链式的 then,可以指定一组按照次序调用的回调函数。这时,前一个 then 里的一个回调函数,返回的可能还是一个 Promise
对象(即有异步操作),这时后一个回调函数,就会等待该 Promise
对象的状态发生变化,才会被调用。由此实现异步操作按照次序执行。
var sayhello = function (name) { return new Promise(function (resolve, reject) { setTimeout(function () { console.log(name); resolve(); //在异步操作执行完后执行 resolve() 函数 }, 1000); }); } sayhello("first").then(function () { return sayhello("second"); //仍然返回一个 Promise 对象 }).then(function () { return sayhello("third"); }).then(function () { console.log('end'); }).catch(function (err) { console.log(err); }) //输出:first second third end
上面代码中,第一个 then 方法指定的回调函数,返回的是另一个Promise
对象。这时,第二个then
方法指定的回调函数,就会等待这个新的Promise
对象状态发生变化。如果变为resolved
,就继续执行第二个 then 里的回调函数
4、Generator 函数
// 用 co 模块自动执行 var co = require('co'); var sayhello = function (name, ms) { setTimeout(function (name,ms) { console.log(name); }, ms); } var gen = function* () { yield sayhello("xiaomi", 2000); console.log('frist'); yield sayhello("huawei", 1000); console.log('second'); yield sayhello("apple", 500); console.log('end'); } co(gen());