2017-03-17 3 views
1

Ich habe folgenden Dienst in TypeScript, die Daten aus dem Back-End abruft.Proper Promise Behandlung Erfolg und Fehler Callbacks

Als Parameter der Funktion getAllPropertiesByAppId habe ich einen Erfolg und Fehler Callback.

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 
      } 
     }); 
} 

Dann verwende ich diesen Dienst in meiner Aktion Schöpfer:

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)); 
    }); 
} 

Also, wenn ich InitProperties Aktion Schöpfer nennen nennt es getAllPropertiesByAppId und wenn alles in Ordnung ist, werde ich Versand Aktionen ShoppingCartPropertiesLoaded und ShoppingCartPropertiesDone.

Ich habe einfache Komponente zu speichern, verbunden ist, und die Komponente Fehler auslösen, wenn die Render-Methode

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

public render(): JSX.Element { 

    throw 'SomeError'; 
} 
} 

Die nicht behandelte Ausnahme in der Anweisung Fang endet ausführt von holen.

Ich habe etwas verpasst, wie Versprechen richtig oder sogar besser zu beenden, wie Funktion/Callback als Anweisung aufrufen und Versprechen zu verlassen, um zu vermeiden Ausnahme Ausnahme von Callback in Catch-Anweisung von fetch?

Vielen Dank für Ihre Hilfe

Antwort

2

Als Parameter der Funktion getAllPropertiesByAppId habe ich Erfolg und Fehler Callback.

Und das ist Ihr tatsächliches Problem. Sie sollten immer eine Zusage von einer asynchronen Funktion zurückgeben. Keine Callback-Parameter mehr verwenden!Diese

/** 
* 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[]>(); 
    }); 
} 

wird übrigens lösen Ihr Problem mit nicht behandelten Ablehnungen lesen

sollte Ihr Code. Indem Sie die Kette nicht beenden, sondern das Versprechen zurückgeben, legen Sie - wie üblich - die Verantwortung für die Fehlerbehandlung auf den Aufrufer. Auch der Aufrufer ist implizit verantwortlich für alles, was er in seine Versprechen Callbacks tut - sie betreffen überhaupt nicht die Methode der Rückgabe von Versprechen.

Sie würden daher

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

perfekt verwenden, das ist genau das, was ich suchte! Danke Bergi! –

0

Wenn Sie nicht eine Ausnahme in einem Versprechen Kette fangen wollen, müssen Sie nur den .catch Anruf am Ende entfernen.

Aber bedenken Sie, dass Sie diesen Fehler nicht mit einem try {} catch (error) {} Block abfangen können. Stattdessen wird es bis zu dem Punkt sprudeln, wo Sie eine unhandledRejection auf der obersten Ebene erhalten.

Wenn ich richtig verstanden habe, übergeben Sie einen Rückruf (success) an getAllPropertiesByAppId, die eine Zusage zurückgibt, die den Rückruf aufruft; fetch(…).then(success) grundsätzlich. Was Sie also erleben, ist vollständig das definierte Verhalten von Ausnahmen innerhalb von Funktionen, die in Versprechen eingeschlossen sind.

Sie möchten vielleicht auf die Verwendung von Versprechen den ganzen Weg wechseln, anstatt Fortsetzungsart (Rückrufe) und Versprechen zu mischen.

So etwas wie (in Pseudo-Code-js, nicht ts leider)

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

// … 

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

eine Ausnahme in einem geschickten Komponente Werfen wird dann innerhalb der .catch in der Verheißung Kette nach dem Aufruf von dispatchAllTheThings gefangen werden .