2017-01-31 34 views
0

我有一個函數「mapTranslations」,它從服務器獲取數據,然後映射它。目前我使用回調來返回數據。我不想使用承諾,但我沒有辦法就如何返回映射的數據而不是來自「somePromiseReturningFunction」的數據。 JS Promise:返回映射數據

function mapTranslations(callback){ 
    somePromiseReturningFunction(...).then(function (languageData) { 
     var translations = {}; 
     languageData.d.results.forEach(function (obj) { 
      translations[obj.key] = obj[browserLang]; 
     }); 
     callback(translations); 
    }); 
} 

使用這樣的:

mapTranslations(function(translations){ 
    console.log(translations); 
}); 

目標:

mapTranslations().then(function(translations){ 
    console.log(translations) //Example, wouldn't be an anonymous function 
}); 

回答

1

我建議你回到原來的承諾,從.then()處理這樣的返回值(更解釋如下):

function mapTranslations(){ 
    return somePromiseReturningFunction(...).then(function (languageData) { 
     var translations = {}; 
     languageData.d.results.forEach(function (obj) { 
      translations[obj.key] = obj[browserLang]; 
     }); 
     return translations; 
    }); 
} 

// usage 
mapTranslations().then(function(results) { 
    // access results here 
}).catch(function(err) { 
    // handle error here 
}); 

當您從.then()處理程序返回一個值時,該處理程序將成爲返回的承諾的解析值,並且調用者將看到該值。因此,您可以修改原始承諾中的返回值,並將其返回到您自己的.then()處理程序中。

此外,你真的不希望在回調中包裝承諾。這只是拋棄了承諾的所有優點(鏈的能力,自動異步錯誤傳播,管理/協調多個異步操作的能力,與其他異步操作的互操作性等)。相反,只需返回承諾,並讓調用方在返回的承諾中使用.then()即可訪問數據或錯誤。僅供參考,在您提出的回調代碼中,您正悄悄地吃掉somePromiseReturningFunction()的任何錯誤。如果它拒絕了它返回的承諾,那麼你沒有處理程序,因此調用者永遠不會知道。如果你只是從你的函數返回承諾,那麼錯誤處理是免費的。


僅供參考,您可能需要使用.reduce(),而不是.forEach(),因爲它與對齊更好一點你在做什麼:

function mapTranslations(){ 
    return somePromiseReturningFunction(...).then(function (languageData) { 
     return languageData.d.results.reduce(function(translations, obj) { 
      translations[obj.key] = obj[browserLang]; 
      return translations; 
     }, {}); 
    }); 
} 
+0

是的,這正是我所期待的。我沒有現在你可以像這樣回報它。當然,在回調中包裝承諾並不是要走的路 - 這就是我寫這個問題的原因。 :) – sandrooco

+0

@Sandrooco - 我增加了一個新建議,用'.reduce()'而不是'.forEach()'來縮短代碼。 – jfriend00

+0

看起來不錯 - 爲什麼翻譯在第二次迭代中未定義? – sandrooco

1

像這樣的事情應該做,該then可以返回一個值它會返回您可以使用的新承諾。

function mapTranslations(){ 

    return somePromiseReturningFunction(...).then(function (languageData) { 
     var translations = {}; 
     languageData.d.results.forEach(function (obj) { 
      translations[obj.key] = obj[browserLang]; 
     }); 
     return translations; 
    }); 

} 

mapTranslations().then(....).catch(...);