避免从后台异步请求

时间:2017-06-14 14:24:26

标签: javascript angular typescript promise

我有一个非常大的请求需要15秒才能返回数据。我希望在用户登录时调用该请求,以减少他们进入加载数据的路径所需的时间(他们可以在完成后到达那里,这会立即显示数据,或者可能没有完成,但只让他们在那一刻等待几秒钟)。

因此,当用户登录并获得成功时,我会请求大型数据集:

this.getDataService.getAsyncData(data.LinkToken); // This loads request from data service

然后我在返回时将数据保存到本地存储中,然后当用户登陆从ngOnOnit()发出请求的路径时可以检索该数据

getAsyncData(linkToken){ //this is background request that is loading while user navigates through app
   this.httpC.get(this.baseUrl + "/AccountInfo/Data?linkToken=" + linkToken + "&deliveryTypeId=" + 0 + "&pickupLocationId=" + 0 + "&paymentTypeId=" + 0).map((res:Response) => res.json()).subscribe(res => {
       this.asycCollection = res;
       this.globalService.setData(this.asycCollection) //This passes this data to service that stores in local storage
       console.log(this.asycCollection);
    })
}

然后,该数据可以作为承诺请求从该路由加载时加载的组件返回

//This sets local storage with the data
setData(refillObject:any){ 
    this.refillObj = refillObject;
    window.localStorage.setItem("refillData", JSON.stringify(this.refillObj))
}
//This gets promise of that background async call
getData(){
    let refillInformation:any = window.localStorage.getItem("refillData");

    return new Promise<any>((resolve, reject) => resolve(refillInformation));
}

然后从我的路由组件中我想要检索此数据但仅在它完成加载数据时,否则它返回null,当然没有任何作用。因此,如果用户快速导航到此页面,则它返回null(因为请求尚未完成加载数据)并且爆炸,但如果用户在请求完成后返回,则它全部按设计工作。

如何在加载完成后等待并获取数据?请记住,这是一个后台异步请求,来自用户登录时我从本地存储中检索而不向REST Svc发出新请求。

组件代码:

getAsyncRefills(success){
    this.globalService.getData().then(data => { //everything below this blows up if the page is loaded before the data request has finished loading to local storage.
        this.orderData = JSON.parse(data);
this.currentDeliveryType = this.orderData.DeliveryTypes.find((item) => 
item.DeliveryTypeId == this.orderData.DeliveryTypeId);
        this.currentPaymentArr = this.currentDeliveryType.PaymentTypes;
        this.currentPickupLocations = this.currentDeliveryType.PickupLocations;


        this.setOptions();
        this.buildOrders();

    })

}

2 个答案:

答案 0 :(得分:0)

我会通过以下方式解决这个问题。

我会建立一个负责

服务
  • 在后端触发重度查询的执行
  • 公开显示查询结果到达时发出的 Observable 作为公共属性
    • 一旦数据从后端到达,它将使用公开属性公开的 Observable 发出数据

服务通过依赖注入注入到执行登录的组件和需要显示数据的组件中。

登录成功后,执行登录的组件会调用触发查询的服务方法。

需要显示数据的组件可以使用服务公开属性的 Observable 来显示数据到达后的数据。有几种方法可以做到这一点。您可以使用Angular中的 async 管道,它允许您直接在模板中引用 Observable ,或者您可以订阅 Observable 然后使用订阅逻辑中定义的函数来填充所需的变量。

答案 1 :(得分:0)

对于这样的事情,我不会使用本地存储,但会使用服务(抱歉没有IDE,所以代码可能不完美)。

@Injectable()
export class ExpensiveDataStore {

  private expensiveData_: ConnectableObservable<ExpensiveThing>;
  private connection: Subscription;

  get expensiveData(): Observable<ExpensiveThing> {
    if(!this.expensiveData_) {
      throw Error('Must initialize store first!');
    }
    return this.expensiveData_;
  }

  initialize() {
    this.expensiveData_ = this.goFetchExpensiveData().publishLast();
    this.connection = this.expensiveData.connect();
  }

  void reset() {
    this.connection.unsubscribe();
    this.connection = this.expensiveData.connect();
  }

}

app.component.ts或某些高级别组件中,您可以拨打initialize()。在需要数据的组件中,您只需订阅expensiveData