【问题标题】:Typescript - subscription inside iteration打字稿 - 迭代内的订阅
【发布时间】:2021-09-22 05:00:17
【问题描述】:

我试图为“myArray”变量中的每个值反复调用“getData”API。每次它从“getData”调用中获取新数据时,我都试图将结果推送到一个数组,以便我可以操作代码的“destinationArray”部分中的值。但是,由于 typescript 不是异步的,它会在 .subscribe / 完成迭代之前到达“destinationArray”代码。

我已经尝试使用 await waitUntil(() => done==true, { timeout: 10015 }); 解决此问题 但我不断在控制台中随机出现消息说ERROR Error: Uncaught (in promise): Error: Timed out after waiting for 10015 ms。天真的答案是将超时时间增加到无穷大,但实际的 API 调用本身并不需要 10 秒,大约需要 1 秒(即使有那么长)。 我怎样才能让它等到它完成迭代/订阅后再移动到底部的“destionationArray”部分,而不会在控制台中看到超时错误消息?

let dataFromAPIcall: any[] = []
let myArray: any[] = ["hello","world"]
for(let i = 0; i< myArray.length; i++) {    
    this.GetDataSubScription = this.myService.getData(myArray[i]).pipe( takeUntil(this.ngUnsubscribe) ).subscribe(data => {
        dataFromAPIcall.push(data)
        if(i+1 == myArray.length) {
            done = true
        }
    });
}

await waitUntil(() => done==true, { timeout: 10015 });
                    
let destinationArray: any[] = [];
for(let i = 0; i < dataFromAPIcall.length; i++) {
    destinationArray[i] = [dataFromAPIcall[i].something1, dataFromAPIcall[i].something2]
}

【问题讨论】:

    标签: arrays typescript asynchronous async-await observable


    【解决方案1】:

    您可以zip您的 api 调用并以反应方式处理所有响应,而无需使用命令式状态变量:

    在所有 observables 发出后,将值作为数组发出

    // creating an array of observables. The requests are not fired yet.
    const requests = myArray.map(i => this.myService.getData(i));
    const destinationArray: any[] = [];
    
    // passing the request array to the zip function.
    // this will actual initiate the requests and emit when ALL
    // requests are done
    zip(...requests).pipe(
      tap(responses => {
          // maping responses to destinationArray
          destinationArray = responses.map(dataFromAPIcall => [dataFromAPIcall.something1, dataFromAPIcall.something2])
      }),
      tap(_ => {
        // continue here
      })
    ).subscribe();
    

    【讨论】:

    • 不错的方法!
    • 2 个问题... 1. .subscribe 之后的任何代码是否会在数组中的所有请求都完成后仅执行? 2.如果我想将响应存储在目标数组中,我是否只需在“responses.map(...)”之前添加一个“destinationArray =”?
    • 订阅后的代码立即执行。我已经更新了我的答案。 destinationArray 现在已更新,我留下了评论,您可以在其中执行代码。
    猜你喜欢
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    • 2020-12-06
    • 1970-01-01
    • 2021-10-20
    • 2019-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多