【问题标题】:Angular 9 typescript how to make a function with a for loop to finish first before proceeding to the next function?Angular 9 typescript 如何使一个带有for循环的函数先完成,然后再继续下一个函数?
【发布时间】:2020-11-13 20:24:46
【问题描述】:

我目前正在学习更多关于 angular 和 typescript 的异步方面的知识,如果我缺乏知识,请原谅我,我目前正面临一个问题,我正在尝试实现 promise 以创建一个包含 for 循环完成的函数首先在调用下一个函数之前,

这是一个示例代码,目标是我有一个 for 循环来遍历所有表单,并且在循环中,是调用服务以获取要放入对象中的必要数据,然后继续创建一个新的具有所述数据的对象并将新创建的数据推送到数组中,在此函数结束后,下一个函数将运行以将数组提交给服务。

例如我有一个大小为 2 的表单,我希望在调用最后一个 resolve() 返回 submitObj() 并最终调用 sendTestObject() 之前结束 for 循环,

在component.ts中

 submitObj() {

    // call function to create object and wait for it to finish
    // via a promise.then()
    this.createTestObject().then((){

        //then finally call another service to give created object
        this.sendTestObject();
    });
    
}
 
 
 createTestObject() {
    const testObjList: testActvity[] = [];
    let count = 1;
    return new Promise ((resolve) => {

    // How do I make it so that this for loop goes in order
    // and finishes first
    // before going to the next line of code?
    for (const i in this.testFormArray.controls) {
      testObj = new Actvity();
      let promise = new Promise((resolve,reject) =>{
      
      this.testService.getTestData().then(res => {
        console.log(count);
        if (res) {
            if (res.results) {
                this.testArrayForm.controls[i].get('testForm').patchValue({
                    "Id": res.results.Id,
                    "type": res.results.type,
                })
            }
        }      
      })}
      
      resolve();
    }
  });
  
  promise.then(()=> {
     console.log("in then() of " + count);
     testObj.testForm = this.testArrayForm.controls[i].get('testForm').value;
     testObjList.push(testObj);
     count ++;
  })

  //How do I wait for the for loop to finish first before running this?
  console.log("FINISHED)"
  resolve();
}

在service.ts中

getTestData(): Promise<any>{
    let res = this.http.get("testData.json")
    .toPromise()
    .then( res => {
      return res ;
    }). catch (err => {
        return err ;
    });
     return new Promise ((resolve, reject) => {
       resolve(res);
     });
 }

【问题讨论】:

    标签: angular typescript es6-promise asynchronous-javascript


    【解决方案1】:

    这是我的解决方案。我没有使用您的代码,因为我无法对其进行测试,但我正在展示总体思路。基本上我摆脱了for 循环,而是在元素上迭代(在你的情况下是表单输入),如果承诺的话,会形成一个递归链。一旦最后一个解决了,我们就知道我们已经处理了所有元素:

    const data = ['foo', 'bar'];
    
    function processElement(index: number): void {
        console.log('do something with element: ' + index + ' which is: ' + data[index]);
    }
    
    function processAllElements(index: number, count: number): Promise<void> {
        return new Promise((resolve, reject) => {
            if(index == count) {
                resolve();
                return;
            }
            
            processElement(index);
            
            return processAllElements(index + 1, count);
        });
    }
    
    function run(): void {
        processAllElements(0, data.length)
            .then(() => {
                console.log('All done');
            });
    }
    
    run();
    

    【讨论】:

      【解决方案2】:

      为什么不使用“concat”rxjs 运算符(Angular 可以很好地与可观察对象配合使用,而无需使用 Promise)?一个简单的例子:

      如果我们有一个返回 observable 的函数:

      obs(value){
         return of(value).pipe(delay(1000))
      }
      

      并连接一个可观察的数组

      const $concatObs=concat(...[0,1,2,3].map(x=>this.obs(x)));
      

      我们可以订阅

      $concatObs.subscribe(res=>{
            this.value=res;
      })
      

      一个simple stackblitz

      更新“cacth 错误”。如果我们的函数可以抛出错误,则 concat 的问题。好吧,我们可以使用 catchError(另一个 rxjs 运算符)来计算这一点。

      如果我们将 observables “管道化”以使其在出现错误时返回一个对象 {error:....}

      const $concatObs = concat(
        ...[0, 1, 2, -2, 3, 4,"finished"].map(x => this.obs(x)
           .pipe(catchError(error=>{
                return of({error:error})
            })))
      );
      

      在订阅中我们可以检查是否有错误

      $concatObs.subscribe(res => {
        if (res.error)
        {
          console.log(res.error)
        }else
          this.value = res;
      });
      

      【讨论】:

        猜你喜欢
        • 2023-01-13
        • 2018-04-20
        • 2021-10-15
        • 2018-07-10
        • 1970-01-01
        • 2021-12-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多