简体   繁体   English

如何使用Angular 4在可观察对象内部进行http promise调用?

[英]Using Angular 4 how do I make a http promise call inside of an observable?

Using Angular 4 how do I make a http promise call inside of an Observable? 如何使用Angular 4在Observable内部进行http promise调用? I am using AWS API Gateway with Cognito Federated accounts. 我正在使用具有Cognito联合帐户的AWS API Gateway。 We have to use the apigClient.invokeApi to sign each http call. 我们必须使用apigClient.invokeApi对每个http调用进行签名。 I want to get the results of promise call and return the result as an observable. 我想获取promise调用的结果,并以可观察的方式返回结果。 The code below fires but does not get to the rest of the observable code at all. 下面的代码可以触发,但根本无法到达其余的可观察代码。 When I subscribe to the observable it never gets to the code inside of the subscribe. 当我订阅可观察对象时,它永远不会到达订阅内部的代码。 I am not getting any compile errors either. 我也没有任何编译错误。 Any help would be helpful. 任何帮助都会有所帮助。

public upload(image, fileType): Observable<FileReturnData> {
  const apigClient = apigClientFactory.newClient({
    accessKey: this.auth.cognitoAccessKey,
    secretKey: this.auth.cognitoSecretKey,
    sessionToken: this.auth.cognitoSessionToken,
    invokeUrl: this.auth.URL
  });
  const data = new FileData()
  data.image = image;
  data.fileType = fileType;
  const uploadPromise = apigClient.invokeApi({}, '/users/upload', 'POST', {}, {image: image, fileType: fileType});


const observable = new Observable<FileReturnData>(observer => {

    uploadPromise.then(function (uploadResult) {
      console.log(uploadResult); // I see this in the console

      const fileReturnData = new FileReturnData();

      const responseBody = JSON.parse(uploadResult.body);

      fileReturnData.filename = responseBody.filename;
      console.log('IN OBSERVABLE');  //  I never get to this result
      observer.next(fileReturnData);
      observer.complete();


      return () => console.log('upload image user observable disposed');

    }).catch(function (uploadImageError) {

      return () => console.error(uploadImageError);
    });

  });

  return observable;

}

I only use nested promises with Ajax calls like this but I believe your issue with your code, using observables and a nested promise is that you prematurely start the invokeApi http call, the call to /users/upload is not completing when you expect it to, thus subscribers of the observable returned by upload awaiting a observer.complete() will have unintended consequences because you are calling observer.complete() in uploadPromise.then which may have already completed or my not have completed yet. 我只对这样的Ajax调用使用嵌套的promise,但是我相信您的代码问题,使用可观察的对象和嵌套的promise是您过早启动invokeApi http调用,对/users/upload的调用未按预期完成,因此通过upload返回的observable的订户正在等待observer.complete(),这会产生意想不到的后果,因为您正在uploadPromise.then中调用observer.complete()uploadPromise.then可能已经完成或尚未完成。

See if this fixes your code: 看看这是否可以解决您的代码:

  public upload(image, fileType): Observable<FileReturnData> {
      const apigClient = apigClientFactory.newClient({
        accessKey: this.auth.cognitoAccessKey,
        secretKey: this.auth.cognitoSecretKey,
        sessionToken: this.auth.cognitoSessionToken,
        invokeUrl: this.auth.URL
      });

    const observable = new Observable<FileReturnData>(observer => {

        const data = new FileData()
        data.image = image;
        data.fileType = fileType;

        apigClient.invokeApi({}, '/users/upload', 'POST', {}, {image: image, fileType: fileType})
        .then(function (uploadResult) {
          console.log(uploadResult); // I see this in the console

          const fileReturnData = new FileReturnData();

          const responseBody = JSON.parse(uploadResult.body);

          fileReturnData.filename = responseBody.filename;
          console.log('IN OBSERVABLE');  //  I never get to this result
          observer.next(fileReturnData);
          observer.complete();

        }).catch(function (uploadImageError) {

          //handle error
        });

      });

      return observable;

    }

I personally find using nested promises for http calls easier to manage if I am understanding your scenario entirely. 如果我完全了解您的情况,我个人发现对HTTP调用使用嵌套的Promise比较容易管理。 Here is a version of your code you can use, that uses promises only and then any Observable can call upload and await its completion: 这是您可以使用的代码版本,仅使用Promise,然后任何Observable都可以调用upload并等待其完成:

  public upload(image, fileType): Promise<FileReturnData> {
      const apigClient = apigClientFactory.newClient({
        accessKey: this.auth.cognitoAccessKey,
        secretKey: this.auth.cognitoSecretKey,
        sessionToken: this.auth.cognitoSessionToken,
        invokeUrl: this.auth.URL
      });



    const promise = new Promise<FileReturnData>((resolve, reject) => {

        const data = new FileData()
        data.image = image;
        data.fileType = fileType;
        //I moved this "invokeApi" call here because it does not seem like a factory method
        //it seems like you start an ajax call when "invokeApi" is called
        //so you must keep this all within the promise you are returning to callers
        //of the upload function
        apigClient.invokeApi({}, '/users/upload', 'POST', {}, {image: image, fileType: fileType})
        .then(uploadResult => {
          console.log(uploadResult); // I see this in the console

          const fileReturnData = new FileReturnData();

          const responseBody = JSON.parse(uploadResult.body);

          fileReturnData.filename = responseBody.filename;

          resolve(fileReturnData);

        }, msg => {
            reject(msg);
        }).catch(ex => {
          return () => console.error(ex);
        });

      });

      return promise;

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM