2012-06-23 37 views
1

我的理論可能會有點弱,所以請隨時告訴我。Javascript Kango:如何在非異步函數中獲取異步JS函數的返回值?

此代碼是使用Kango framework的瀏覽器插件的一部分。基本上我有代碼生成一個用戶ID的隨機字符串。我還有另外一個設置JSON的函數。它看起來像這樣:

function createJSON() { 
data = {}; 
data["userID"] = generateID(); 
} 

function generateID() { 
kango.invokeAsync('kango.storage.getItem', 'userID', function(data) { 
    uid = data; 

    if (!uid) { 
     console.log("uid doesn't exist, creating uid!"); 
     kango.invokeAsync('kango.storage.setItem', userID, function(data) { return data; }); 
    } else { 
     console.log("uid found!: " + uid); 
     return uid; 
    } 

    return data; 
    }); 
} 

kango.invokeAsync docs are here。我的理解是它有點像一個異步ajax調用,在這種意義上,它不會及時返回,當我試圖將其值賦給數據[「userID」]時。

我想我可以通過先做userID調用,然後使用它的回調(在這裏對術語有些模糊)來繼續並添加到數據數組來解決此問題。

我不知道,如果這是正確的方式來做到這一點,雖然。我如何獲得異步函數的返回值?

+0

請做n不要使用標題作爲標籤的位置。 SO的標記系統工作正常。乾杯。 – Kgrover

回答

2

由於generateID()的異步特性,你不能這樣做。它會返回前的異步調用已完成,因此數據不可用:

data["userID"] = generateID(); 

相反,你必須使用這樣的回調:

generateID(function(val) {data["userID"] = val;}); 

function generateID(callback) { 
kango.invokeAsync('kango.storage.getItem', 'userID', function(data) { 
    uid = data; 

    if (!uid) { 
     console.log("uid doesn't exist, creating uid!"); 
     kango.invokeAsync('kango.storage.setItem', userID, function(data) { callback(data); }); 
    } else { 
     console.log("uid found!: " + uid); 
     callback(uid); 
    } 

    }); 
} 

當使用異步函數,則不能使用正常的順序編程。相反,您必須在完成回調中繼續執行流程,因爲ONLY是異步函數的結果。

因此,您將無法致電createJSON()並從中返回所需的值。如果createJSON()之後的任何代碼需要結果,則它也必須處於回調中。

+0

如果您必須進行多個異步調用並從中獲取價值,該怎麼辦?這是否意味着你必須保持「嵌套」的調用,以便一個不執行,直到值已知等?我是否正確? –

+0

@ dsp_099 - 是的,如果您有多個連續的異步調用,則必須嵌套您的呼叫。 – jfriend00

1
function createJSON() { 
    data = {}; 
    generateID(function(id) { 
    data["userID"] = id; 
    }); 
} 

function generateID(callback) { 
    kango.invokeAsync('kango.storage.getItem', 'userID', function(data) { 
    uid = data; 

    if (!uid) { 
    console.log("uid doesn't exist, creating uid!"); 
    kango.invokeAsync('kango.storage.setItem', userID, function(data) { callback(data); }); 
    } else { 
    console.log("uid found!: " + uid); 
    callback(uid); 
    } 

    callback(data); 
}); 
} 

這會適合您嗎?

1

您不能從異步調用返回對象。而是創建另一個函數並將回調對象傳遞給它。

// some code 
if (!uid) { 
    console.log("uid doesn't exist, creating uid!"); 
    kango.invokeAsync('kango.storage.setItem', userID, function(data) { 
    getData(data); 
    }); 
} else { 
    console.log("uid found!: " + uid); 
    getData(uid); 
} 

function getData(data) { 
    // Use data here. 
} 
3

看看更接近來自documentation的invokeAsync示例。

在你的代碼有兩個失誤與invokeAsynckango.storage.setItem電話:

kango.invokeAsync('kango.storage.setItem', 'userID', '123');  

所以,結果代碼將是這樣的:

// 1. Second argument should be string 'item name' 
// 2. Third argument should be 'item value' 
kango.invokeAsync('kango.storage.setItem', userID, function(data) { callback(data); }); 

你應該以這種方式使用kango.storage.setIteminvokeAsync

function generateID(callback) { 
    kango.invokeAsync('kango.storage.getItem', 'userID', function(uid) { 
     if(!uid) { 
      kango.console.log("uid doesn't exist, creating uid!"); 
      uid = '123'; // TODO: replace with your ID generation algorithm 
      kango.invokeAsync('kango.storage.setItem', 'userID', uid); 
     } 
     else { 
      kango.console.log("uid found!: " + uid); 
     } 
     callback(uid); 
    }); 
} 

data = {}; 
generateID(function(uid) { 
    data["userID"] = uid; 
}); 
+0

感謝您的支持。 –