2017-07-04 80 views
0

我想知道是否有可能將回調的值分配給一個變量。我最近遇到了MongoClient的連接方法問題,我想要獲取數據庫對象並將其傳遞給我的類方法。有沒有一種方法可以將hello world指定爲var b打破回調鏈 - 節點

function testCB(cb){ 
    setTimeout(() => { 
    cb('Hello World') 
    }, 1000) 
} 

let b = testCB('a', (str) => { 
    return str; 
}) 

console.log(b) //undefined 
+0

使用異步方法(setTimeout是異步的)意味着您必須編寫代碼來處理異步...沒有什麼能夠將異步代碼更改爲同步 - 另外,'testCB'函數甚至沒有return語句,所以它永遠不會返回任何東西 –

+2

你可以把'b = str;'放在回調中,但是'console.log(b)'仍然會顯示'undefined',因爲它在回調運行之前運行。想一想:如果你可以以某種方式神奇地將回調中的值分配給'b' *同步*,爲什麼你需要首先回調? –

回答

0

由於事件是異步的,您需要遵循異步代碼流程。因此,爲了「獲得回報」的唯一途徑是你的回調函數內,即:

function testCB(cb){ 
    setTimeout(() => { 
    cb('Hello World') 
    }, 1000) 
} 

let b = testCB('a', (str) => { 
    // this executes async, when testCB finishes running 
    console.log(str) // will print STR 
    return str; 
}) 
// this code executes BEFORE testCB finish running, 
// so it is imposible to get the value of str here. 

如果你想有一個更流暢的代碼,你可以嘗試使用承諾與asyncawait它們可在節點7+

0

當前,您正在調用b調用testCB的結果,但testCB不返回任何內容,因此沒有任何內容分配給b

但沒有什麼不對的模式:

var b; 

testCB((str) => { b = str; }); 

這是保持一個變量(b)應用程序的狀態,並修改狀態異步函數的簡單版本。

如果應用程序的很多部分依賴於b並且您想要同步定義該依賴關係,那麼這就是Promises的用途!

在這種情況下,你可以定義:

var b = new Promise((resolve, reject) => { 
    setTimeout(() => resolve('Hello World'), 1000); 
}); 

b.then((str) => {...do something with str...} 
b.then((str) => {...do something else with str...} 
doSomeThingWithB(b); 

其中當然doSomeThingWithB知道b是一個承諾(或 「thennable」)。

+0

「*這個模式沒什麼問題*」 - 當然有:所有使用'b'的代碼都不知道它是否已經被賦值。 – Bergi

+0

@Bergi但是,當你異步修改狀態變量時,情況總是如此。在「b」中「訂閱變更」和處理「未定義」狀態的問題是一個不同的問題,而不是OP要求的。問題是如何「突破」回調範圍。 –

+0

我很確定他打算「打破回調範圍」,同時仍然做同樣的事情。不能把'console.log'放在回調之外,或者至少是一個單獨的範圍。 – Bergi