2016-04-28 113 views
9

我有一個承諾,即返回數據,我想將它保存在變量中。在JavaScript中這是不可能的,因爲異步性質,我需要使用onResolve作爲回調嗎?如何從Promise中提取數據

我可以以某種方式使用它(例如,用異步包起來/等待):

const { foo, bar } = Promise.then(result => result.data, errorHandler); 
// rest of script 

,而不是這個?

Promise.then(result => { 
    const { foo, bar } = result.data; 
    // rest of script 
}, errorHandler); 

注:藍鳥庫是用來代替機實現,我不能承諾變爲asnyc /等待或發電機。

+0

這可能與JavaScript。您可以將承諾成功時收到的數據分配給您之前聲明的變量。而你的變量將具有你從承諾中得到的價值。 您可以參考: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise –

+0

['async/await'](https://tc39.github.io/ ecmascript-asyncawait /)即將到來! –

+0

@SandipNirmal這是可能的,但可能會導致錯誤,因爲JavaScript不會等待Promise解決。還需要將'const'更改爲'let',這會產生副作用。 –

回答

9

不,您不能同步獲取數據超出您在示例中所建議的承諾。數據必須在回調函數中使用。在函數式編程風格中,承諾數據可以是map()ed over

如果你確定使用async/await(你應該很棒),那麼你可以編寫看起來同步的代碼,但保留承諾的異步性(參見@loganfsmyth comments)。

const { foo, bar } = await iAmAPromise.then(result => result.data); 

總的來說你已經在使用ES6我假設你也在使用一個轉譯器。在這種情況下,你一定要給異步/等待一試。 只要確定權重的決定,因爲今天他們還沒有一個批准的規範。

+0

_「這很棒」_自從什麼時候阻塞真棒? – zeroflagL

+0

@zeroflagL異步不會比承諾回調阻塞更多。該線程可以自由地處理其他內容(即,如果在NodeJS中爲新請求),而執行將在承諾解決後恢復。這只是一種不同的語法。 – silkAdmin

+0

停止執行該功能。它不與'Promise.then'。因此,如果您在瀏覽器中的「事件處理程序」中等待結果,那肯定不是很棒。 – zeroflagL

1

雖然您可以從異步函數中的期待Promise中獲取值(因爲它暫停了等待結果的函數),但您無法直接從Promise中獲取值並返回到相同範圍作爲承諾本身。

這是因爲「超出」意味着嘗試將未來存在的東西(最終解析的值)放到上一個已經發生的上下文(同步變量賦值)中。

也就是時間旅行。即使時間旅行是可能的,但它可能不是一個好的編碼習慣,因爲時間旅行可能會令人困惑。:)

一般來說,如果你發現自己感覺你需要這樣做,那很好表明你需要重構某些東西。請注意,您正在使用「的結果=> result.data」在這裏做什麼:

Promise.then(result => result.data, errorHandler); 
// rest of script 

..是已經你一起工作的情況下(從字面上看,在映射)將它傳遞給一個值功能。但是,假設「//腳本的其餘部分」與此值有重要關係,您可能希望繼續將現在更新的值與另一個函數進行映射,然後再使用該值執行一些副作用-y(如在屏幕上顯示數據)。

Promise 
    .then(result => result.data) 
    .then(data => doSomethingWithData)// rest of script 
    .catch(errorHandler); 

「doSomethingWithData」將被調用(如果以往任何時候的稱呼)在未來的某個未知點。這就是爲什麼將所有這些行爲清楚地封裝到特定函數中然後將該函數掛接到Promise鏈上的良好習慣。

這樣說實話更好,因爲它要求你清楚地聲明一個特定的事件序列,將會發生,明確地從第一次運行通過所有應用程序代碼的執行中分離出來。

換一種方式,想象一下這個場景,在全球頂級範圍假設執行:

const { foo, bar } = Promise.then(result => result.data, errorHandler); 
console.log(foo); 
//...more program 

什麼,你會希望有發生?有兩種可能性,而且它們都不好。

  1. 整個程序(的console.log一切 之後自帶)將停止,等待承諾執行 ,才能夠知道什麼是「富」會......不,可能是。 (這是 什麼是「等待」,一個異步函數內部,確實在事實上做:它會暫停 整個函數,直到值或錯誤回來)
  2. foo和酒吧只會是不確定的(這是實際 ),因爲如同步執行,它們只是 Promise對象的不存在的屬性(它不是值, ,但Monad包裝最終值或錯誤),其中大多數 可能不甚至包含一個值。