2017-08-29 79 views
4

比方說,我有一個文件從api導入函數並對結果進行處理。在JavaScript中返回Promise es6

import api from './api' 

const getData =() => { 
    api.get(url) 
    .then(res => console.log(res)) 
    .catch(err => console.log(err)) 
} 

我見過兩種不同的樣式用於返回響應,以便錯誤起泡。

版本1:

get: (url) => { 
    return new Promise((resolve, reject) => axios.get(url) 
    .then(res => resolve(res)) 
    .catch(err => reject(err))) 
} 

版本2:

get: (url) => { 
    return axios.get(url) 
    .then(res => { 
     if (res.success == 200) { 
     return Promise.resolve(res) 
     } 
     return Promise.reject(res) 
    }) 
} 

什麼是兩種方法之間的差異?有錯誤處理的首選/更好的方法嗎?

+0

'then'還有一個可選的第二個回調參數,可以用來代替鏈接'catch'。 – Igor

+0

版本1 =>您返回一個待解決或拒絕的承諾。版本2 =>您稍後返回一個已解決或拒絕的承諾 – Fefux

回答

2

一般來說,二得心應手規則:

  1. 如果你的出發點是一個承諾(的axios.get返回值),然後用new Promise是一個反模式。 thencatch已經創造新的承諾。

  2. 傳播錯誤,不要將它們轉換爲分辨率(當然,直到您處理這些錯誤的位置,通常靠近調用鏈的開頭)。

此基礎上,那兩個選項,你會使用版本  2,不要版  1.

版本  1是一個有點無厘頭:它吃的分辨率值和轉換錯誤決議;它將始終解析爲undefined。請記住,鏈的結果是thencatch處理程序中返回(或拋出)的最後一件事的結果。這兩個處理程序不會返回或拋出任何東西,因此該鏈可以用undefined解決(而不是拒絕)。

版本  2做某事:它根據res.success修改承諾結果。不過,這並不需要Promise.resolve,它應該僅僅是:

get: (url) => axios.get(url).then(res => { 
    if (res.success == 200) { 
    return res; 
    } 
    return Promise.reject(res); // Or see note below 
}) 

而且還有一個營地  —我與  —它說同意你應該總是拋出一個Error對象,而不是返回Promise.reject,堆棧跟蹤信息。所以:

get: (url) => axios.get(url).then(res => { 
    if (res.success == 200) { 
    return res; 
    } 
    throw new Error(res/*...or something else useful here...*/); 
}) 
+0

*(如果您看到*「版本1是無稽之談,它與...完全相同」*請點擊刷新。)* –

+0

讓我們假設api.get在React組件中被調用,並且我希望組件呈現錯誤消息...我會使用版本2嗎? –

+0

@crashspringfield:這很好,如果代碼是最終用戶,那麼你將會使用一個'catch'處理程序(或者'then'的第二個參數),以及2.不會將承諾傳播出去方法(通常不常用;在極少數情況下,你希望處理*和*傳播錯誤,在這種情況下,在處理完成後''拋出'catch'處理程序)。這確實很像第1版,只是沒有回覆承諾。 –

0

沒有與這兩個版本沒有真正的區別,在第一個,你正在創建一個冗餘Promise

axios.get,是一個返回Promise的函數,不需要用另一個包裝它。

如果您想更改承諾邏輯,則意味着如果您想解決不管發生在axios承諾中的事情,您可以額外支付Promise。 類似的東西:

get: (url) => { 
    return new Promise((resolve, reject) => axios.get(url) 
    .then(res => resolve(res)) 
    .catch(err => resolve(err))) 
} 

,但通常它不是慣例。

+0

*「這兩個版本沒有真正的區別」*第一個人通過將分辨率值轉換爲分辨率來消除分辨率值並將其隱藏起來的事實是一個相當大的差異。 :-) –

+0

這是一種可能的用法,不建議這樣做,但有時您需要打包SDK或類似的東西。 :] – felixmosh