正确的承诺处理成功和错误回调

问题描述:

我在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语句中的回调异常?

非常感谢您的帮助

作为函数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! –

如果你不想搭上一个承诺链内的例外,你只需要去掉末尾的.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后。