2017-06-14 80 views
0

我有一个非常大的请求,需要15秒才能返回数据。我想在用户登录时调用这个请求,以减少他们进入加载数据的路径所需的时间(他们可以在完成后到达那里,这会立即向他们显示数据,或者它可能没有完成,但只能让他们在那一刻等待几秒钟)。如何避免从后台返回空数据异步请求角度2-4

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

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

    }) 

} 
+0

你有使用localStorage的原因吗?还有为什么你在一个应用程序中使用Observables和Promises?我假设缓慢的异步请求 - 以及后来需要来自LocalStorage的数据的代码是相同的应用程序是否正确? – MikeOne

+0

我试着单独使用observable或promise,但它仍然加载空值,所以我在添加本地存储之前只是为了确保我最终可以获取对象,但这绝不是一个完成的想法.v它们确实都是相同的应用程序。我目前正在研究使用EventEmitter来订阅服务中的事件,它在返回时发出检索到的数据,也有点磕磕绊绊(当数据返回时,订阅发出的值而不是调用函数)。如果你有一个建议,我很高兴与它一起运行。 –

回答

0

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

我将建立一个服务有责任

  • 火灾重查询在后台执行
  • 公开为公共财产的可观察发出的结果时,的查询已到达
    • 一旦数据从后端到达,它就会使用发出数据Observable公开为公共属性

服务注入,经由依赖注入,到执行的登录和需要来显示该数据的组件的组件。

登录成功后,执行登录的组件将调用启动查询的服务的方法。

需要显示的数据可以通过服务使用公开为公共财产可观察来显示数据,一旦他们到达的组成部分。有几种方法可以做到这一点。您可以使用从角的异步管,它允许您直接引用可观测模板,或者您可以订阅可观察,然后用在订阅逻辑定义的函数,以填补所需的变量。

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