把一些異步操作整合到下一個(gè)CPU時(shí)間片執(zhí)行冰沙,比多個(gè)異步操作多次調(diào)用setTimout(fn,0)的效率要高(摘自美團(tuán)前端團(tuán)隊(duì))
/**
* 將函數(shù)延遲執(zhí)行
*
* @param {Function} fn 希望被延遲執(zhí)行的函數(shù)
* @param {Object} context 執(zhí)行函數(shù)時(shí)上下文環(huán)境
* @param {...} args 執(zhí)行調(diào)用多個(gè)參數(shù)
* @access public
* @return {Number} 等待執(zhí)行的任務(wù)數(shù)
*
* @example
*
* var fn = function(){
* console.log(2);
* };
*
* nextTick(fn);
* console.log(1);
*
* // 1
* // 2
*/
'use strict';
(function (global, undefined) {
var callbacks = []; //等待調(diào)用的函數(shù)棧
var running = false; //當(dāng)前是否正在運(yùn)行中
var slice = [].slice;
var setImmediate = global.setImmediate || function (fn) {
return global.setTimeout(fn, 0);
};
//調(diào)用所有在函數(shù)棧中的函數(shù)
//如果在執(zhí)行某函數(shù)時(shí)又有新的函數(shù)被添加進(jìn)來(lái)户矢,
//該函數(shù)也會(huì)在本次調(diào)用的最后被執(zhí)行
function callAllCallbacks() {
var cbs = callbacks;
callbacks = [];
running = false;
var count = cbs.length;
for (var index = 0; index < count; index++) {
var callback = cbs[index];
var fn = callback[0];
var context = callback[1];
fn.apply(context, callback.slice(2));
}
}
function nextTick(fn, context, args) {
var callback = slice.call(arguments);
//將函數(shù)存放到待調(diào)用棧中
callbacks.push(callback);
//判斷定時(shí)器是否啟動(dòng)
//如果沒(méi)有啟動(dòng)履恩,則啟動(dòng)計(jì)時(shí)器
//如果已經(jīng)啟動(dòng)砌些,則不需要做什么
//本次添加的函數(shù)會(huì)在 callAllCallbacks 時(shí)被調(diào)用
if (!running) {
running = true;
setImmediate(callAllCallbacks, 0);
}
return callbacks.length;
}
if (typeof module === 'object' && module && typeof module.exports === 'object') {
module.exports = nextTick;
} else if (typeof define === 'function' && define.amd) {
define('nextTick', [], function () {
return nextTick;
});
} else {
global.nextTick = nextTick;
}
})(typeof global === 'object' ? global : window);