承诺中的多重承诺

时间:2018-02-01 15:54:01

标签: javascript typescript asynchronous promise

我想建立then链,但我的承诺在内部承诺执行之前得到解决。我该如何解决这个问题?

此代码工作正常,但我想将其设为线性承诺链

functiontest(abc):Promise<any> {

return new Promise((resolve, reject) => {
     this.nativeStorage.getItem('test')
    .then(test => {
            if(test == 1) {
                this.function2(abc).then(tagId=>{
                    this.function3(tagId).then(data=>{
                        resolve(data)
                    });
                });
            }else {
                this.function3(abc).then(data=>{
                    resolve(data)
                });
            }         
        },
        error => {
            this.function2(abc).then(tagId=>{
                this.function3(tagId).then(data=>{
                    resolve(data)
                });
            });       
        }
    )      
});  }
仅当function3被调用时,

function2才会使用function2的结果,否则会直接调用function3

3 个答案:

答案 0 :(得分:3)

您的代码实际上太复杂了。当您从new Promise获得getItem时,不需要使用.then(...then(....then())),并且应该避免嵌套像function test(abc): Promise<any> { return this.nativeStorage.getItem('test') .then(test => { if (test == 1) { return this.function2(abc); } return abc; }) .catch(() => this.function2(abc)) .then(tagId => this.function3(tagId)); } 这样的承诺处理程序。

以下代码在功能上应与您的代码相同:

async

您可能还希望将await / {{1}}作为一种以更简单的方式实现异步功能的方法。

答案 1 :(得分:2)

由于您使用的是typescript,因此使代码更具可读性的最佳方法是使用async / await:

<form [formGroup]="myForm">
  Playername: <input formControlName="player" type="text" ><br>
</form>

TotalPoint: 14 <br>
totalPointInTournament: 9 <br>
totalPointInTournament: 5 <br>


<pre>
  {{myForm.value |json}}
</pre>




 import { Component, OnInit } from '@angular/core';
    import { FormGroup, FormControl, FormBuilder, Validators, FormArray, 
    ReactiveFormsModule, AbstractControl } from '@angular/forms';

    @Component({
     selector: 'app-contact', 
   templateUrl: './contact.component.html',
   styleUrls: ['./contact.component.css']
    })
    export class ContactComponent implements OnInit {

  myForm: FormGroup;

  constructor(private fb: FormBuilder) { }

  ngOnInit() {

    this.myForm = this.fb.group({
      player: new FormControl(''),
      totalPoint: '14',
      weeks: this.fb.array([
        this.fb.group({
          totalPointInTournament: '9',
          matches: this.fb.array([
            this.fb.group({
              point: '5'
            }),
            this.fb.group({
              point: '4'
            })
          ])
        }),
        this.fb.group({
          totalPointInTournament: '5',
          matches: this.fb.array([
            this.fb.group({
              point: '3'
            }),
            this.fb.group({
              point: '2'
            })
          ])
        })
      ])
    }
    );

    this.updateStats();

  }

  updateStats() {

    this.myForm.get('weeks').valueChanges.subscribe(val => {

      // Calculate total point here..
      console.log('val' + JSON.stringify(typeof (val)));


    });
  }

}

答案 2 :(得分:1)

因为您似乎陷入困境我认为您可能想要考虑应用程序的控制流应该是什么,因为在查看您的代码然后在您的评论中它目前没有多大意义。然后用模拟测试它,然后用真实函数测试它。

这是简化的functionTest函数,它可以完成代码所做的工作(不可能在注释中执行您想要的操作,因为这与您的代码实际执行的操作相冲突)。使用mock thisObject(你可以在控制流正确时将thisObject设置为this)。

const later = value => 
  new Promise(
    (resolve,reject)=>
      setTimeout(
        _=>resolve(value),
        1000
      )
  )
const thisObject = {
  getItem : item => {
    if(item===-1){
      const p = Promise.reject("nope");
      p.catch(ignore=>ignore);//stops the console from shouting
      console.log("in getItem, rejecting with 'nope'");
      return later(p);//return rejected promise without rejection handled
    }
    console.log("in getItem resolving to:"+item);
    return later(item);
  },
  function2 : item => {
    console.log("in function2 with argument:",item);
    return later("function2")
  },
  function3 : item => {
    console.log("in function 3 with argument:",item);
    return later("function3-"+item)
  }
}
const functionTest = abc => {
  //thisObject=this
  return thisObject.getItem(abc)
  .then(//if getItem succeeds
    test =>
      //call fn2 or fn3 with abc (do not pass getitem result to the functions)
      //  depending on getItem result
      (test == 1)
        ? thisObject.function2(abc)//1: call function2 with abc
        : thisObject.function3(abc),//not 1: cll function3 with abc
    error =>//if getItem fails
      //call function2 with abc and function3 with result of function2
      thisObject.function2(abc)
      .then(
        tagId =>
          thisObject.function3(tagId)
      )
  );
}
document.querySelectorAll("input").forEach(
  (el,index)=>el.addEventListener(
    "click",
    e=>
      functionTest(index-1)
      .then(
        result=>console.log("finished, result is:",result)
      )
  )
);
<input type="button" value="getItem that rejects">
<input type="button" value="getItem that resolves to 0">
<input type="button" value="getItem that resolves to 1">