如何重复承诺链中的步骤以及如何从失败的步骤中恢复?

时间:2017-04-01 01:21:58

标签: typescript promise ionic2

我是JS / TS的新手,因此Promises,我成功地编写了我的" Steps"作为从C#移植的承诺,但我将采取你可以概述的任何构造。 (使用ionic2 / TS)。

为什么承诺: 我在TS中使用Promise,以便在幻灯片集合中播放幻灯片时对一系列任务进行排序。 (不确定我是否正确使用了promises,也许还有其他的构造,模式需要考虑,请告诉我)

我的目标: 如何构建承诺链:

  1. 我可以迭代一系列步骤......
  2. 我可以重复Step2()说5次吗?
  3. 从Step1()失败中恢复并继续下一个索引/幻灯片(所有后续步骤)。
  4. 这是我目前的代码大纲

    PlayAll() {
    
        Step1(Index)
            .then(() => {
                console.log("PlayAll<<promise------------Step1 DONE");
                Step2(i)
                    .then(() => {
                        console.log("PlayAll<<promise------------Step2 DONE");
                        if (Index < Count) {
                            Index++;
                            // tell slider to move and wait for its change event
                        // ??? 
                        }
                        else
                            // -) Report we are done with all Slides
                            // Perhaps I should write PlayAll as a promise too?
                            // instead of using a Callback ??
                            if (typeof (this.Done) == "function")
                                this.Done(); // a registered callback.
                    }
                    .catch(() => {
                    console.log("PlayAll<<promise------------Step2 FAIL");
                    }
    
            .catch(() => {
                    console.log("PlayAll<<promise------------Step1 FAIL");
            }
    }
    

    我的Step1()看起来像这样

        // Using Howler.js (makes audio work on Android)
        // https://stackoverflow.com/questions/30069988/how-can-i-create-a-promise-for-the-end-of-playing-sound
        // 20160820
        PlayOne(Media: string) {
            console.log("AudioPlayList------------>>PlayOne Media is", Media);
            return new Promise((resolve, reject) => { // return a promise
                var audio = new Howl({ src: [Media] });                     // create audio wo/ src
                // cache a class level copy for other methods, eg. pause
                this.audio = audio;
                //
    // TODO: needs help:
    // not sure how to code reject here ???
    // does this look correct?          
                // audio.on('error', () => {
                //     console.log("AudioPlayList<<e------------audio ERROR");
                //     reject(Media);
                //     return reject;
                // });      
    
                audio.on('end', () => {
                    console.log("AudioPlayList<<e------------audio ENDED");
                    resolve(Media);
                    return resolve;
                });                     // when done, resolve
                audio.play();
            });
        }
    

    我的Step3()未在上面的大纲中显示,如下所示

    timer1: any;  // needed to abort Slide's PostPause, if user alters playback
    
      // https://www.typescriptlang.org/docs/release-notes/typescript-1.7.html
      // 20160812
      private SlidePostPause() {
        console.log("PlayAll------------>>PostPause");
        return new Promise<void>(
          resolve => {
            this.timer1 = setTimeout(resolve, this.Model.PostPause * 1000);
          });
      }
    

    此链接 How to return from a Promise's catch/then block

    说      _从拒绝处理程序返回常规值会导致调用下一个.then()解析处理程序(例如正常处理继续)_

    这是我通常想要的。

    我也读过这个链接 https://github.com/basarat/typescript-book/blob/master/docs/promise.md

    但我仍然输了:)

    请尽可能明确。

    感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

这是我到达的代码。我可以使用while循环重复一连串的promise。从失败的承诺中恢复依赖于正确的拒绝,最初我使用Howler.js播放的声音没有记录事件的正确拼写,并在此回放所需的嵌套承诺中引起奇怪的行为。

一切正常,因为我希望期望在TypeScript中可能不支持动态更改while循环限制,因此在当前行为中,一旦进入循环,似乎改变计数不会生效直到下一张幻灯片开始,从而发出下一个while循环。

我想我可以阅读这个承诺。从现在开始六个月后再开始理解它:) 我不知道在TypeScript中支持async / await,我想知道它如何在这方面有所改进。

    //  
    this.PlaySlideRepetitions(Index).then(() => {
      console.log("AMSController<<promise------------PlaySlideRepetitions DONE ");
      //
      if (Index < this.AMSData.Count) {
        console.log("AMSController<<------------>> Play Next Slide");
        // Tell View to Update 
        // NOTE: this will cause the view SlideChanged() to call back in here PlayIndex()
        this.AMSView_I.SlideNext();
      }
      else {
        console.log("AMSController<<----------->> DONE playing all slides");
        this.Done();
      }
    });



  // 20170403
  PlaySlideRepetitions(Index: number) {
    let DynamicCount = this.GlobalService.AMSRepeatCount_;
    let chain = Promise.resolve({});  // trick to kick off this darn Promises :)
    var i = 0;
    while (i < DynamicCount) {
      chain = chain.then(() => {
        return this.PlaySlideOnce(Index).then(() => {
          console.log("AMSController<<promise------------PlaySlideOnce DONE " + i);
        })
          .catch(() => {
            console.log("AMSController<<promise------------PlaySlideOnce FAIL " + i);
          });
      });
      i++;
      DynamicCount = this.GlobalService.AMSRepeatCount_; // may be altered by user
    }
    return chain;
  }
  // 20170401
  PlaySlideOnce(Index: number) {
    console.log("AMSController------------>>PlaySlideOnce Index=", Index);
    return new Promise((resolve) => {
      // Step 1
      this.AudioPlayList.Play(this.AMSData.Audio(Index))
        .then(() => {
          console.log("AMSController<<promise------------AudioPlayList DONE");
          // Step 2  
          this.SlidePostPause()
            .then(() => {
              console.log("AMSController<<promise------------SlidePostPause DONE");
              resolve();
            })
            .catch(() => {
              console.log("AMSController<<promise------------SlidePostPause FAIL");
            });
        })
        .catch(() => {
          console.log("AMSController<<promise------------AudioPlayList FAIL");
          // return 123;
          // return Promise.resolve(123);
        });
    });
  }

感谢所有建议