【问题标题】:angular how to await subscribe角度如何等待订阅
【发布时间】:2018-01-10 10:40:07
【问题描述】:

我是 Angular 应用程序的新手。我不完全了解subscribe 的工作原理。我目前的障碍是我不明白为什么console.log("B")console.log("A") 之前执行,因此呈现一个空数组的结果(请参阅console 输出的链接)。

我尝试将所有代码放入带有async/await 的函数中以等待该函数。我不明白为什么它不起作用。

在这种情况下等待订阅的最佳方式是什么?

console.log("B") 必须在console.log("A") 之后执行。

this._roleService.getRoleTypes(this.token).subscribe(
    response => {
        if(response.status != "error" && response.code != 400){
            let _roleTypes:Array<RoleType> = new Array<RoleType>(); 
            _roleTypes = new Array<RoleType>();
            response.data.forEach(rt => {
                let roleType:RoleType = new RoleType(
                    rt.id,
                    rt.name
                );
                _roleTypes.push(roleType);
            });
            console.log("A");
            console.log(_roleTypes);
            this.roleTypes = _roleTypes;
        }
        else{
            this._loginService.destroySession();
        }
    },error => {
        this.errorMessage = <any>error;
        if(this.errorMessage != null){
            console.log(this.errorMessage);
            alert("Petition Error");
        }
    }
);
console.log("B");
console.log(this.roleTypes);

【问题讨论】:

    标签: javascript angular typescript


    【解决方案1】:

    您可以使用 toPromise 方法实现此目的。这也是处理异步操作的好方法。只需删除 subscribe 并添加此方法,然后在调用此方法的方法中添加 async 关键字即可。

    例子-

     const response = await this._roleService.getRoleTypes(this.token).toPromise();
    

    所以,现在您将首先获得 console.log("A"),然后是 console.log("B")。

    【讨论】:

    • 这是一个很好的答案。我会对此投双票。我很惊讶没有人将其标记为答案。这绝对等待订阅。
    【解决方案2】:

    如果您需要同步执行代码,您应该使用 async/await。将您的订阅代码包装在一个返回承诺的函数中。

    async getRolestypes(): Promise<Array<RoleType>> {
    
       return new Promise((resolve, reject) => {
    
         this._roleService.getRoleTypes(this.token).subscribe(
           response => {
             if(response.status != "error" && response.code != 400){
              let _roleTypes:Array<RoleType> = new Array<RoleType>(); 
              _roleTypes = new Array<RoleType>();
              response.data.forEach(rt => {
                let roleType:RoleType = new RoleType(
                    rt.id,
                    rt.name
                );
                _roleTypes.push(roleType);
               });
              console.log("A");
              console.log(_roleTypes);
              resolve(_roleTypes);
           }
           else{
               this._loginService.destroySession();
               reject('not a good response')
           }
           },error => {
            this.errorMessage = <any>error;
            if(this.errorMessage != null){
               reject(this.errorMessage);
            }
          }
        );
    
    
      })
    
    
    }
    
    
    this.roleTypes = await getRolestypes();
    console.log(this.roleTypes);
    

    【讨论】:

      【解决方案3】:

      您可能知道,订阅用于处理异步方法调用。因此,subscribe() 方法中的代码只有在异步方法返回其结果时(例如在 http 调用之后)才会执行。

      在等待异步响应时,程序继续执行以下代码。这就是异步调用的目标!

      这就是为什么您的console.log('B') 在您的console.log('A') 之前执行。

      这是一个例子:

      this.myservice.asyncCall().subscribe( (result) => {
         // wait for the async response
         console.log('I get some data from asyncCall()');
      });
      // sync code executed, even if the previous async call doesn't respond anything
      console.log('Code executed after the subscription. But not waiting for it to respond');
      

      如果您希望自己是 console.log('B'),则必须将其移至您的订阅功能(在 else 语句之后)。您还可以从该位置调用方法,具体取决于您要查找的目的。

      您也可以查看.map() 方法。这允许您在 subscribe 方法中处理检索到的响应之前对其进行编辑(添加一些数据、转换它、记录或任何事情)。

      【讨论】:

      • 对不起..做多个非异步操作的最佳方法是什么?
      • “多个非异步操作”是什么意思?每一个代码行都是一个非异步操作。只有一些最后需要“订阅”的方法是异步的。
      • 可以使用await吗?
      • Await 旨在模拟异步方法上的同步行为。您的代码将等待 Promise 完成,然后再转到下一行。所以这里的目的不一样!但是是的,es6 await/async 可以与 angular 2+ promises 一起使用。在 angularjs 上,看看 $q。
      【解决方案4】:

      @sunny 上面的回答是我的首选。但是toPromise 在 RxJs 7 中已被弃用,可能不会出现 当 RxJs 8 发布时。所以新的方法是:

      import { lastValueFrom } from 'rxjs';
      
      const roleTypes$ = this._roleService.getRoleTypes(this.token);
      const response = await lastValueFrom(roleTypes$);
      

      【讨论】:

        【解决方案5】:

        订阅是异步执行的。在您的情况下, subscribe 将执行,然后 console.log('B') 将在此之后执行。稍后,当 Observable 发布响应(基于成功/错误)时,将调用相应的成功/错误回调。所以你可以在成功回调中处理 console.log('B')

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-18
          • 2021-05-06
          • 1970-01-01
          • 2021-06-08
          • 1970-01-01
          • 2019-03-14
          • 2017-11-11
          • 2020-12-02
          相关资源
          最近更新 更多