當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
短小强悍的JavaScript异步调用库
生活随笔
收集整理的這篇文章主要介紹了
短小强悍的JavaScript异步调用库
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原文鏈接: ?7 lines JavaScript library for calling asynchronous functions?
翻譯人員: 鐵錨
翻譯時間: 2014年02月18日
示例地址: 簡短強悍的JavaScript異步調用庫在線調試
對于博文 20行完成一個JavaScript模板引擎 的備受好評我感到很驚訝,并決定用此文章介紹使用我經常使用的另一個小巧實用的工具.我們知道,在瀏覽器中的 JavaScript 絕大部分的操作都是異步的(asynchronous),所以我們一直都需要使用回調方法,而有時不免陷入回調的泥淖而欲死欲仙.
假設我們有兩個 functions ,我們順序地在一個后面執行完后調用另一個。他們都操作同一個變量。第一個設置它的值,第二個使用它的值。
var value; var A = function() {setTimeout(function() {value = 10;}, 200); } var B = function() {console.log(value); }那么,現在如果我們運行 A();B(); 我們將在控制臺看到輸出為 undefined . 之所以會這樣是因為 A 函數使用了異步方式設置 value 。我們能做的就是傳一個回調函數給A,并讓函數A在執行完后執行回調函數。
var value; var A = function(callback) {setTimeout(function() {value = 10;callback();}, 200); }; var B = function() {console.log(value); };A(function() {B(); });這樣確實有用,但想象一下加入我們需要運行5個或更多方法時將會發生什么。一直傳遞回調函數將會導致混亂和非常不雅觀的代碼。
好的解決辦法是寫一個工具函數,接受我們的程序并控制整個過程。讓我們先從最簡單的開始:
var queue = function(funcs) {// 接下來請看,董卿??? }接著,我們要做的是通過傳遞A和B來運行該函數 - queue([A, B])。我們需要取得第一個函數并執行它。
var queue = function(funcs) {var f = funcs.shift();f(); }如果執行這段代碼,您將看到一個 TypeError: undefined is not a function。這是因為 A函數沒收到回調參數但卻試圖運行它。讓我們換一種調用方法。
var queue = function(funcs) {var next = function() {// ...};var f = funcs.shift();f(next); };在 A執行完后會調用 next 方法。將下一步操作放在 next 函數列表中是個很好的做法。我們可以將代碼歸攏在一起,而且我們能夠傳遞整個數組(即便數組中有很多函數等待執行)。
var queue = function(funcs) {var next = function() {var f = funcs.shift();f(next);};next(); };到了這一步,我們基本上達到了我們的目標。即函數A 執行后,接著會調用 B,打印出變量的正確值。這里的關鍵是 shift 方法的使用。它刪除數組的第一個元素并返回該元素。一步一步執行下去, funcs數組就會變成 empty(空的)。所以,這可能會導致另一個錯誤。為了證明這一觀點,讓我們假設我們仍然需要運行這兩個功能,但我們不知道他們的順序。在這種情況下,兩個函數都應該接受回調參數(callback )并執行它。
var A = function(callback) {setTimeout(function() {value = 10;callback();}, 200); }; var B = function(callback) {console.log(value);callback(); };當然,我們會得到 TypeError: undefined is not a function.?
要阻止這一點,我們應該檢查funcs數組是否為空。
var queue = function(funcs) {(function next() {if(funcs.length > 0) {var f = funcs.shift();f(next);}})(); };我們所做的就是定義 next 函數并調用它。這種寫法減少了一點代碼。
讓我們試著想象盡可能多的情況。比如當前執行功能的 scope 。函數內的 this 關鍵字可能指向了全球的 window 對象。,如果我們可以設置自己的scope 當然是件很酷的事情。
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {var f = funcs.shift();f.apply(scope, [next]);}})(); };我們為這個tiny 類庫增加了一個參數。接著我們使用 apply ?函數,而不是直接調用 f(next),來設置scope 并將參數 next 傳遞進去。同樣的功能,但漂亮多了。
我們需要的最后一個特性,就是是函數間傳遞參數的能力。當然我們不知道具體會有多少參數將被使用。這就是為什么我們需要使用 arguments 變量的原因。你可能知道,該變量在每個 JavaScript函數中都是可用的,代表了傳進來的參數。它就和一個數組差不多,但不完全是。因為在 apply 方法中我們需要使用真正的數組,使用一個小竅門來進行轉換。
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {var f = funcs.shift();f.apply(scope, [next].concat(Array.prototype.slice.call(arguments, 0)));}})(); };下面是測試的代碼:
// 測試代碼 var obj = {value: null };queue([function(callback) {var self = this;setTimeout(function() {self.value = 10;callback(20);}, 200);},function(callback, add) {console.log(this.value + add);callback();},function() {console.log(obj.value);} ], obj);執行后的輸出為:
30 10為了代碼的可讀性和美觀,我們將部分相關的代碼移到一行內:
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0)));}})(); };你可以 點擊這里查看并調試相關代碼 ,完整的測試代碼如下:?
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0)));}})(); };var obj = {value: null };queue([function(callback) {var self = this;setTimeout(function() {self.value = 10;callback(20);}, 200);},function(callback, add) {console.log(this.value + add);callback();},function() {console.log(obj.value);} ], obj);
翻譯人員: 鐵錨
翻譯時間: 2014年02月18日
示例地址: 簡短強悍的JavaScript異步調用庫在線調試
對于博文 20行完成一個JavaScript模板引擎 的備受好評我感到很驚訝,并決定用此文章介紹使用我經常使用的另一個小巧實用的工具.我們知道,在瀏覽器中的 JavaScript 絕大部分的操作都是異步的(asynchronous),所以我們一直都需要使用回調方法,而有時不免陷入回調的泥淖而欲死欲仙.
假設我們有兩個 functions ,我們順序地在一個后面執行完后調用另一個。他們都操作同一個變量。第一個設置它的值,第二個使用它的值。
var value; var A = function() {setTimeout(function() {value = 10;}, 200); } var B = function() {console.log(value); }那么,現在如果我們運行 A();B(); 我們將在控制臺看到輸出為 undefined . 之所以會這樣是因為 A 函數使用了異步方式設置 value 。我們能做的就是傳一個回調函數給A,并讓函數A在執行完后執行回調函數。
var value; var A = function(callback) {setTimeout(function() {value = 10;callback();}, 200); }; var B = function() {console.log(value); };A(function() {B(); });這樣確實有用,但想象一下加入我們需要運行5個或更多方法時將會發生什么。一直傳遞回調函數將會導致混亂和非常不雅觀的代碼。
好的解決辦法是寫一個工具函數,接受我們的程序并控制整個過程。讓我們先從最簡單的開始:
var queue = function(funcs) {// 接下來請看,董卿??? }接著,我們要做的是通過傳遞A和B來運行該函數 - queue([A, B])。我們需要取得第一個函數并執行它。
var queue = function(funcs) {var f = funcs.shift();f(); }如果執行這段代碼,您將看到一個 TypeError: undefined is not a function。這是因為 A函數沒收到回調參數但卻試圖運行它。讓我們換一種調用方法。
var queue = function(funcs) {var next = function() {// ...};var f = funcs.shift();f(next); };在 A執行完后會調用 next 方法。將下一步操作放在 next 函數列表中是個很好的做法。我們可以將代碼歸攏在一起,而且我們能夠傳遞整個數組(即便數組中有很多函數等待執行)。
var queue = function(funcs) {var next = function() {var f = funcs.shift();f(next);};next(); };到了這一步,我們基本上達到了我們的目標。即函數A 執行后,接著會調用 B,打印出變量的正確值。這里的關鍵是 shift 方法的使用。它刪除數組的第一個元素并返回該元素。一步一步執行下去, funcs數組就會變成 empty(空的)。所以,這可能會導致另一個錯誤。為了證明這一觀點,讓我們假設我們仍然需要運行這兩個功能,但我們不知道他們的順序。在這種情況下,兩個函數都應該接受回調參數(callback )并執行它。
var A = function(callback) {setTimeout(function() {value = 10;callback();}, 200); }; var B = function(callback) {console.log(value);callback(); };當然,我們會得到 TypeError: undefined is not a function.?
要阻止這一點,我們應該檢查funcs數組是否為空。
var queue = function(funcs) {(function next() {if(funcs.length > 0) {var f = funcs.shift();f(next);}})(); };我們所做的就是定義 next 函數并調用它。這種寫法減少了一點代碼。
讓我們試著想象盡可能多的情況。比如當前執行功能的 scope 。函數內的 this 關鍵字可能指向了全球的 window 對象。,如果我們可以設置自己的scope 當然是件很酷的事情。
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {var f = funcs.shift();f.apply(scope, [next]);}})(); };我們為這個tiny 類庫增加了一個參數。接著我們使用 apply ?函數,而不是直接調用 f(next),來設置scope 并將參數 next 傳遞進去。同樣的功能,但漂亮多了。
我們需要的最后一個特性,就是是函數間傳遞參數的能力。當然我們不知道具體會有多少參數將被使用。這就是為什么我們需要使用 arguments 變量的原因。你可能知道,該變量在每個 JavaScript函數中都是可用的,代表了傳進來的參數。它就和一個數組差不多,但不完全是。因為在 apply 方法中我們需要使用真正的數組,使用一個小竅門來進行轉換。
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {var f = funcs.shift();f.apply(scope, [next].concat(Array.prototype.slice.call(arguments, 0)));}})(); };下面是測試的代碼:
// 測試代碼 var obj = {value: null };queue([function(callback) {var self = this;setTimeout(function() {self.value = 10;callback(20);}, 200);},function(callback, add) {console.log(this.value + add);callback();},function() {console.log(obj.value);} ], obj);執行后的輸出為:
30 10為了代碼的可讀性和美觀,我們將部分相關的代碼移到一行內:
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0)));}})(); };你可以 點擊這里查看并調試相關代碼 ,完整的測試代碼如下:?
var queue = function(funcs, scope) {(function next() {if(funcs.length > 0) {funcs.shift().apply(scope || {}, [next].concat(Array.prototype.slice.call(arguments, 0)));}})(); };var obj = {value: null };queue([function(callback) {var self = this;setTimeout(function() {self.value = 10;callback(20);}, 200);},function(callback, add) {console.log(this.value + add);callback();},function() {console.log(obj.value);} ], obj);
轉載于:https://www.cnblogs.com/lanzhi/p/6467041.html
總結
以上是生活随笔為你收集整理的短小强悍的JavaScript异步调用库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Doxygen自动文档生成工具在Ecli
- 下一篇: iOS 7开发快速入门