【问题标题】:Angular 5 synchronous HTTP callAngular 5 同步 HTTP 调用
【发布时间】:2018-09-01 20:16:09
【问题描述】:

我有一个 Angular 5 应用程序,我必须在其中调用一些繁重的 REST 服务(通常需要几秒钟)。我需要它的结果在应用程序的不同部分,所以我想将结果存储在 DataStorageService 中。 基本上,这是我想要实现的:

@Injectable()
export class DataStorageService {

private result: MyCustomObject;

constructor(private service: Service) {}

getResult(): MyCustomObject {
    if (typeof this.result === 'undefined') {
        // save result
    }
    return result;
}

问题是我如何才能等到 HTTP 请求完成,然后保存并返回“结果”对象。我也尝试使用 Promise 和 Observable 来解决它,但它们都不能正常工作。

  1. 可观察:

    if (typeof this.result === 'undefined') {
        this.service.call()
            .subscribe(response => this.result = response);
    }
    return this.result;  // wait for save and return MyCustomObject
    
  2. 承诺:

    if (typeof this.result === 'undefined') {
        this.service.call()
            .toPromise()
            .then(response => this.result = response);
    }
    return this.result;  // wait for save and return MyCustomObject
    

【问题讨论】:

  • 你的getResult(): Promise<MyCustomObject> 也应该返回一个promise/observable。午饭回来时,将编码丢失的代码。与此同时,查看github.com/ngrx/store 可能会为该问题带来新的解决方案。
  • 我想避免返回 Promise 或 Observable。我需要根据打开的页面将结果聚合到不同的对象中。如果我总是必须订阅 Promise,这会使我的代码变得如此丑陋。而不是使用简单的对象。
  • 代码清晰和维护注意事项:你的方法命名为getResult(),但它实际上保存了结果,所以行为与名称不匹配,导致混淆
  • 你说得对,大卫。为了更好地理解,我从头开始编写它。也许值得将保存功能移动到 ngOnInit 方法中。
  • 我更新了我的问题,因为原来的问题在不必要的代码中过于含糊。很抱歉。

标签: angular http promise observable


【解决方案1】:

问题是我如何才能等到 HTTP 请求完成,然后保存并返回 're sult' 对象。

// 服务代码:

ServiceMethod:Observabke<any>(){
     if (typeof this.result === 'undefined') {
                return this.service.call().map(res=>res);
}

// 这是组件中的代码。

 componentMethod(){


        return this.service.ServiceMethod()
            .subscribe(response => {
                this.result = response;
               },
               ()=>//handle error,
               () => // call completed { return this.result;  // Subscriber});
    }
    return this.weeklyPlayer;  // MyCustomObject (This return won't wait for http to get completed. Not sure why you want multiple returns.)

    }

希望这会有所帮助。

【讨论】:

  • 不是我的反对意见,但我想这是因为您的代码不会等待 http 调用完成分配并返回值
  • 如果您在谈论“返回 this.weekPlayer”,我在评论中添加了它不会起作用。而对于这个结果,它是在 subsrcibe 中赋值并在调用完成时返回。
  • 我没有投反对票。无论如何,我已经尝试过非常相似的东西。如果我从组件调用此方法,它还会返回订阅者而不是 MyCustomObject。据我了解,我必须使用带有 await/async 的 Promise 来等待服务响应。 Observable 无法解决我的问题。
  • 哦等等。如果你想从组件中调用它,它的另一种方式。我正在更新我的答案。
  • 谢谢 Dheeraj,非常感谢您的帮助。也许我错了,但我认为 Observable 无论如何都无法解决。如果我在组件中调用“getResult()”,它总是返回订阅者而不是我的真实对象。如果我将 Observable 映射到 Promise 并使用 await/async 关键字暂停执行并等待解决,则唯一可行的解​​决方案。
【解决方案2】:

尝试使用await/async

async getResult(): Promise<MyCustomObject> {
    if (typeof this.result === 'undefined') 
    {
        // save result
        this.result = await this.service.call()
        .toPromise()
        .then(resp =>resp as MyCustomObject);//Do you own cast here

    }
    return this.result;
}

【讨论】:

  • 方法签名不应该是:async getResult(): Promise ?
  • 为什么这个答案被认为是正确的?这不是同步的,这只是使用 async/await 而不是 Promise。同步请求必须由 http 库支持,并且必须将底层 xmlHtppRequest 标记为同步。这个问题可能是错误的。 developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/….
【解决方案3】:

我赞成上面大卫的回应,但我认为可能存在设计缺陷。您实际上不应该将结果保存(在本地存储中)getResult 函数中。这是一种副作用,在某些时候它可能是不可取的,并且如果您只想在不保存的情况下获得,您的 getResult 几乎无法重复使用。

如果您想刷新数据,同时拥有this.result === 'undefined' 也可能会产生问题。

所以如果你想在ngOnInit 中得到这些结果,你可以这样做:

ngOnInit() {
    if (typeof this.result === 'undefined') {
        this.getResult().then(result => {
            // save the result here
            this.result = result;

            // save in local storage ...
        });
    }
}

getResult(): Promise<MyCustomObject> {
    return this.service.call().toPromise();
}

请注意,您不能在 ngOnInit 中等待。但是现在您的 getResult() 函数可以在许多其他情况下重复使用。

【讨论】:

  • 这实际上在 David Votrubec 的 OP 的 cmets 中被提及。
猜你喜欢
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-14
  • 2012-05-08
相关资源
最近更新 更多