爲了提升頁面加載效率,愈來愈多的項目都在使用js異步加載。那麼若是多個異步加載結果互相依賴,而且嵌套會發生什麼事情?沒錯就是讓人聞風喪膽的回調地獄。下面咱們就用setTimeout方法來模擬異步加載,分別瞭解下ES6中Promise 和 jquery中 Deferred 都是怎麼解決回調地獄的。javascript
首先咱們來看一下正常狀況下異步加載嵌套是什麼樣的,也就是js回調地獄是什麼樣的java
var myfunc = function() { console.log("start func1");//模擬第一次回調 setTimeout(function() { console.log("start func2"); //模擬第二次回調 setTimeout(function() { console.log("start func3"); //模擬第三次回調 setTimeout(function() { console.log("start func4"); //模擬第四次回調 setTimeout(function(){ console.log("func end") },2000) }, 2000); }, 2000); }, 2000); }
若是業務邏輯再複雜一些,代碼直接不能看了。。。jquery
使用promise.then()鏈式調用,解決回調地獄promise
new Promise(function(res, rej) { console.log("start func1"); setTimeout(res, 2000); }).then(function() { return new Promise(function(res, rej) { console.log("start func2"); setTimeout(res, 2000); }) }).then(function() { return new Promise(function(res, rej) { console.log("start func3"); setTimeout(res, 2000); }) }).then(function() { return new Promise(function(res, rej) { console.log("start func4"); setTimeout(res, 2000); }) }) //執行結果以下 start func1 start func2 start func3 start func4
使用promise.catch()捕獲異常瀏覽器
new Promise(function(res, rej) { console.log("start func1"); setTimeout(res, 2000); }).then(function() { return new Promise(function(res, rej) { console.log("start func2"); console.log(a); setTimeout(res, 2000); }) }).catch(function(msg){ console.log(msg); }) //執行結果以下 start func1 start func2 ReferenceError: a is not defined at <anonymous>:7:18 at new Promise (<anonymous>) at <anonymous>:5:10 at <anonymous>
使用promise.all()同步執行多個異步操做異步
var p1 = new Promise(function (resolve) { setTimeout(function () { resolve("func1 success"); }, 2000); }); var p2 = new Promise(function (resolve) { setTimeout(function () { resolve("func2 success"); }, 2000); }); var p3 = new Promise(function (resolve) { setTimeout(function () { resolve("func3 success"); }, 2000); }); Promise.all([p1, p2, p3]).then(function (result) { console.log(result); console.log("all func success"); }); //執行結果 ["func1 success", "func2 success","func3 success"] all func success
部分瀏覽器對promise可能存在兼容性問題,若是發生兼容性問題能夠使用$.Deferred函數
deferred.then()解決回調地獄spa
function func1(){ var def = $.Deferred(); setTimeout(function(){ def.resolve('func1 result'); }, 2000); return def.promise(); } function func2(){ var def = $.Deferred(); setTimeout(function(){ def.resolve('func2 result'); }, 2000); return def.promise(); } function func3(){ var def = $.Deferred(); setTimeout(function(){ def.resolve('func3 result'); }, 2000); return def.promise(); } func1().then(function(data){ console.log(data); return func2(); }).then(function(data){ console.log(data); return func3(); }).then(function(data){ console.log(data); }) //執行結果 func1 result func2 result func3 result
$.when同步執行多個異步操做,全部異步操做執行完畢,執行回調函數,功能相似於 promise.allcode
$.when(func1(), func2(), func3()) .then(function(data1, data2, data3){ console.log('all success'); console.log(data1, data2, data3); }); //執行結果 all success func1 success func2 success func3 success