「更好」是很難當它涉及到的編程風格來定義所以它很難給一個「最佳」的回答你的問題沒有更多地瞭解你在做什麼,以及如何你的代碼的結構。
也就是說,一個很好的經驗法則是試圖讓您的代碼按照如何描述問題的方式進行組織,而不是編寫只關心控制流的代碼。它並不是一個硬性的規則,一方面你想避免執行所有任務的巨大函數,另一方面你想避免函數太小而跳過太多的函數調用其他函數或回調函數。
首先,讓我們假裝你的代碼只是同步的。大多數語言都是這樣的,它讓Javascript沮喪地迴避了你的恥辱。你可以做的一件事是創建接收參數並返回適當值的函數。例如:
//This puts the "is user admin" logic in a single place
//Also note how we can give a good name for the function. If you have a
//hard time naming the function its a hint that maybe you shouldn't be creating
//the function in the first place.
function isAdmin(userData){
return userData.id === 1;
}
如果代碼被使用一次其短短的幾行,你可以讓他們在線
// Names like "process X" or "do X" are not very descriptive.
//See what I mean by it would be good to know extra context?
function processUser(userData){
// Your AJAX code should handle the JSON.Parse.
// I prefer having the code that does the work receive the JS objects
// because that makes things easier to test and to integrate with other JS code
// (no need to convert things to string just to pass to this function)
if(isAdmin(userData)){
//do
//some stuff
return someValue;
}else{
//do some other stuff
return someOtherValue;
}
}
請注意,我說明確的「返回」在這裏。即使你的代碼實際上沒有返回任何東西,這對於理解向回調的轉換也會很方便。
如果你的代碼變得太大,你可以把它移到其他一些功能:
function processAdmin(user){
// dozens of lines of code...
return someValue;
}
function processUnpriviledgedUser(user){
//...
return someOtherValue;
}
function processUser(userData){
if(isAdmin(userData)){
return processAdminUser(userData);
}else{
return processUnpriviledgedUser(userData);
}
}
function fetchUser(){
//lets pretend that AJAX is synchronous for a moment...
var rawData = $.magicAjax("www.example.com");
var user = JSON.Parse(data);
var val = proccessUser(user);
return val;
}
注意一兩件事,我們得到免費的使用功能是,我們可以從多個地方調用它們:
var result = proccessUnpriviledgedUser({id:2, name:"hugomg"});
console.log(result);
現在,讓我們來回電。如果你所有的「processUser」東西都是同步的,你可以用我之前解釋過的普通函數來重構它。不幸的是,如果你想在裏面做任何AJAX調用或者異步的東西,你不能依賴以前的語句return
。相反,你需要用一個onDone
回調來代替它們,回調函數將會返回你想要返回的東西作爲參數。
例如,我們processUser可能看起來像
function processUser(userData, onDone){
if(isAdmin(userData)){ // <-- we can still use sync code when not doing IO
$.ajax("bla", {success: function(){
//blaz;
onDone(someValue);
});
}else{
//
}
}
function fetchUser(onDone){
$.ajax("www.example.com", {
success: function(data){
var user = JSON.Parse(data);
proccessUser(function(val){
onDone(val);
});
}
});
}
function main(){
fetchUser(function(val){
console.log("Fetched the user", val);
});
}
注意我們如何利用我們用於爲在不同的功能分裂碼相同的規則 - 對代碼的大小和名字仍然適用同樣的想法。唯一的區別是做異步的東西需要使用回調而不是return
。特別是,請注意我們如何將onDone回調添加到fetchUser和proccessUser。我們不僅創建了自己的異步函數,而且回調參數意味着我們不需要對功能結束後調用的函數進行硬編碼 - 就像return
可以追溯到調用我們的任何調用函數,onDone
回調意味着我們跳轉到無論呼叫者希望我們回覆什麼(而不是總是在我們完成時跳到同一個地方)。
proccessUnpriviledgedUser({id:2, name:"hugomg"}, function(result){
console.log(result);
});
最後,我想指出的異步代碼一個很大的缺點就是錯誤處理。爲了處理跨越異步函數的「try-catch」,類似於跨越同步函數的處理方式,您可能還需要傳遞onError
回調以及onDone
回調。因爲這是非常容易的,所以我會建議使用某種類型的庫來幫助管理異步代碼(如果您曾經開始編寫非常規的異步代碼,那麼可以使用基於promise或基於cb的代碼)。
回撥?回調意味着當你調用另一個函數並在這個函數中使用這個回調函數時,你傳遞了一些函數。 [實施例](http://stackoverflow.com/questions/3841454/calling-a-callback-in-javascript?rq=1)。您可以使用簡單的功能。你對簡單功能有任何問題嗎? –
我試圖做的是運行其他函數,一旦執行 – user3665791
_This(retrieveData)_ one或_parse_ one? –