2017-03-17 79 views
1

我在TypeScript中有從後端獲取數據的服務。正確的承諾處理成功和錯誤回調

作爲函數getAllPropertiesByAppId的參數,我有一個成功和錯誤回調。

export class PropertyService implements IPropertyService { 

/** 
* Get all properties 
*/ 
public getAllPropertiesByAppId(appliactionId: string, success: (properties: Array<IPropertyItem>) => void, error: (error: any) => void): void {    

    //set up createRequestStr and requestInit 

    fetch(createRequestStr, requestInit) 
     .then<IPropertyItem[]>((response: Response) => { 
      if (response.status===401) { 
       throw new UnAuthorizedException(); 
      } 
      return response.json<IPropertyItem[]>(); 
     }) 
     .then((response: IPropertyItem[]) => {    
      success(response); 
     }) 
     .catch((reason: any) => { 
      //error handling 
      } 
     }); 
} 

然後我在我的行動的創建者使用這項服務:

initProperties: (appId: string): ActionCreator => (dispatch: Redux.Dispatch, getState:() => IApplicationState) => { 
    "use strict"; 

    console.log("ShoppingCart initProperties - Request all Property"); 

    var service: IPropertyService = kernel.get<IPropertyService>("IPropertyService"); 

    service.getAllPropertiesByAppId(appId, (properties: Array<IPropertyItem>): void => { 

     dispatch(new ShoppingCartPropertiesLoaded(appId, properties)); 
     dispatch(new ShoppingCartPropertiesDone(appId, System.Init.Done));    

    }, (error: any): void => { 
     console.log("ShoppingCart initProperties - error:" + error); 
     dispatch(new ShoppingCartPropertiesDone(appId, System.Init.Error)); 
    }); 
} 

所以,當我打電話initProperties行動的創建者調用getAllPropertiesByAppId,當一切都很好,我會派遣行動ShoppingCartPropertiesLoaded和ShoppingCartPropertiesDone。

我有連接到存儲簡單的組件,並在Render方法執行

export default class TotalPriceList extends React.Component<ITotalPriceListProps, void> { 

public render(): JSX.Element { 

    throw 'SomeError'; 
} 
} 

未處理的異常在獲取的catch語句結束了該組件將拋出錯誤。

我是否錯過了如何正確退出諾言或甚至更好地如何從語句和退出諾言中調用函數/回調,以避免catch語句中的回調異常?

非常感謝您的幫助

回答

2

作爲函數getAllPropertiesByAppId的參數,我有成功和錯誤回調。

這就是你的實際問題。你應該總是從異步函數返回一個承諾。 停止使用回調參數!

您的代碼應閱讀

/** 
* Get all properties 
*/ 
public getAllPropertiesByAppId(appliactionId: string): Promise<IPropertyItem[]> { 
    //set up createRequestStr and requestInit 
    return fetch(createRequestStr, requestInit) 
// ^^^^^^ 
    .then<IPropertyItem[]>((response: Response) => { 
     if (response.status===401) { 
      throw new UnAuthorizedException(); 
     } 
     return response.json<IPropertyItem[]>(); 
    }); 
} 

這與未處理的拒絕會順便解決您的問題。通過不結束鏈接,但返回承諾,您將負責處理錯誤的責任 - 與往常一樣。此外,調用者隱含地承擔他在承諾回調中所做的任何事情 - 它們根本不涉及承諾返回方法。

你會因此使用

service.getAllPropertiesByAppId(appId).then((properties: Array<IPropertyItem>): void => { 
//         ^^^^^ 
    dispatch(new ShoppingCartPropertiesLoaded(appId, properties)); 
    dispatch(new ShoppingCartPropertiesDone(appId, System.Init.Done));    
}, (error: any): void => { 
    console.log("ShoppingCart initProperties - error:" + error); 
    dispatch(new ShoppingCartPropertiesDone(appId, System.Init.Error)); 
}).catch((reason: any) => { 
    // error handling for a failed dispatch 
}); 
+0

完美,這正是我一直在尋找!謝謝Bergi! –

0

如果你不想搭上一個承諾鏈內的例外,你只需要去掉末尾的.catch通話。

但請記住,您將無法通過try {} catch (error) {}塊捕獲此錯誤。相反,它會冒泡到您將收到頂層的unhandledRejection

如果我理解正確,您將傳回一個回調(success)至getAllPropertiesByAppId,它返回一個承諾,調用回調;基本上是fetch(…).then(success)。因此,你所體驗到的完全是在承諾中包含的函數內定義的異常行爲。

您可能希望切換到使用promise,而不是混合延續傳遞樣式(回調)和promise。

喜歡的東西(在僞代碼JS,不是TS對不起)

class Service { 
    getAllPropertiesByAppId (appId) { 
    return fetch(createRequestStr, requestInit) 
      .then(response => response.json()); 
    } 
}; 

// … 

service.getAllPropertiesByAppId(…) 
.then(dispatchAllTheThings) 
.catch(error => { console.log(…); dispatch(…) }) 

投擲派出組件內的異常將被在許鏈.catch內抓調用dispatchAllTheThings後。