2015-06-27 91 views
2

這是我在面試中被問到的一個問題。我知道數組只會返回零,因爲這是異步的,但爲什麼會發生這種情況,以及如何修復它,以便結果數組插入適當的數據?Javascript承諾面試

問題:假設findData是一個函數,它接受查詢對象並返回查詢結果的承諾。還假設someRandomArrayOfQueries是一個查詢對象數組。解釋什麼會通過下面的代碼,爲什麼被打印:

function runMultipleQueries(queries) { 
var results = []; 
queries.forEach(doQuery); 

return results; 

function doQuery(query) { 
    findData(query) 
    .then(results.push.bind(results)); 
} 
} 

function log(value) { 
console.log(value); 
} 

runMultipleQueries(someRandomArrayOfQueries).forEach(log); 
+4

您確定這是_vanilla JavaScript_? –

+1

你需要閱讀關於異步過程的JavaScript。這裏重要的是你不知道時間將花費findData。這個承諾不會阻止這個過程。一個承諾只是一個承諾,當他有數據時,他會執行內部的代碼,或者內部錯誤。返回函數將在之前執行,因爲javascript過程繼續執行代碼。 –

+0

@PaulS。代碼看起來不錯。 –

回答

0

doQuery在將來的某個時候被執行。然而數組立即返回並記錄。因此該數組仍然是空的,並且沒有記錄。 爲了解決這個問題,runMultipleQueries也需要返回一個承諾。那可以例如看起來像這樣。

function runMultipleQueries(queries) { 
    return Promise.all(queries.map(findData)); 
} 
function log(value) { 
console.log(value); 
} 

runMultipleQueries(someRandomArrayOfQueries).then(function(results) { 
    results.forEach(log); 
}); 

如果你想保持runMultipleQueries類似於你還可以創建這樣一個新的承諾原來的,但是這將是不必要的複雜。

function runMultipleQueries(queries) { 
return new Promise(function(resolve, reject) { 
    var results = []; 
    queries.forEach(doQuery); 

    function doQuery(query) { 
    findData(query) 
    .then(function(result) { 
     results.push(result); 
     if(results.length === queries.length) resolve(results); 
    }, reject); 
    } 
}); 
} 

您也可以登錄內部doQuery結果,但那麼你就必須在其結果記錄順序沒有任何保證。此外,這會使你在登錄後更難以做任何其他的結果。

function runMultipleQueries(queries) { 
    queries.forEach(doQuery); 

    function log(value) { 
    console.log(value); 
    } 
    function doQuery(query) { 
    findData(query) 
    .then(log); 
    } 
} 

runMultipleQueries(someRandomArrayOfQueries); 
+0

我是否也可以通過在承諾中添加控制檯日誌來修復它?可以這樣做嗎? – andy246

+0

你可以這樣做 - 我已經添加了另一個例子。但我會建議反對它。 – SpiderPig