问题:
因为递归太深而使用了异步的 setTimeout 清空调用栈,整个递归变成了异步的行为,函数已经提前返回了,现在怎么设置整个递归完成后的回调?
回答:
1 // 无回调 2 function isArray(o) { 3 return toString.apply(o) === '[object Array]'; 4 } 5 function foo(arr) { 6 console.log(arr); 7 if (isArray(arr)) { 8 for (i in arr) { 9 (function(j) { 10 setTimeout(function() { 11 foo(arr[j]); 12 }, 0); 13 })(i); 14 } 15 } 16 } 17 foo([[1, 2], [3, 4]]); 18 19 /* 20 输出: 21 [[1,2],[3,4]] 22 [1,2] 23 [3,4] 24 1 25 2 26 3 27 4 28 */ 29 30 //有回调 31 function isArray(o) { 32 return toString.apply(o) === '[object Array]'; 33 } 34 // 设置一个计数器,标识“已知的还未被遍历的元素数量”,起始值显然为1 35 var cbCounter = 1; 36 function foo(arr, cb) { 37 cbCounter += isArray(arr) ? arr.length : 0; // 把子元素的数加上,因为子元素现在已知了 38 console.log(arr); 39 if (isArray(arr)) { 40 for (i in arr) { 41 (function(j) { 42 setTimeout(function() { 43 foo(arr[j], cb); 44 }, 0); 45 })(i); 46 } 47 } 48 if ((--cbCounter === 0) && (typeof cb === 'function')) cb(); // 前面的--就是把自己刨出去 49 } 50 foo([[1, 2], [3, 4]], function() { 51 console.log('I am a callback!'); 52 }); 53 54 /* 55 输出: 56 [[1,2],[3,4]] 57 [1,2] 58 [3,4] 59 1 60 2 61 3 62 4 63 I am a callback! 64 */
字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁字数补丁