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

Posted

技术标签:

【中文标题】如何重复一系列承诺中的步骤以及如何从失败的步骤中恢复?【英文标题】:How to repeat a step in a chain of promises and How to recover from a failed step? 【发布时间】:2017-08-26 09:07:15 【问题描述】:

我是 JS/TS 的新手,因此是 Promises,我设法将我的“步骤”写成从 C# 移植的 Promise,但我会采用您可以概述的任何结构。 (使用 ionic2/TS)。

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

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

    我可以遍历一系列步骤... 我可以重复 Step2() 说 5 次吗? 从 Step1() 失败中恢复并继续下一个索引/幻灯片(所有后续步骤)。

这是我当前的代码大纲

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://***.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

但我还是迷路了:)

请尽可能明确。

感谢您的帮助。

【问题讨论】:

有趣。也许您需要一个带有状态的自定义类来处理它。强迫它进入承诺链会很麻烦。 例如,您可以查看this 以了解如何管理状态。这只是一个为什么要这样做。还有很多其他方式:github.com/unional/assert-order 试试async/await怎么样?用它编写重试/恢复逻辑会更容易。 @Haocheng 你能提供一个你的想法的大纲。谢谢。 【参考方案1】:

这是我到达的代码。我可以使用 while 循环重复一系列承诺。从失败的 Promise 中恢复依赖于正确的拒绝,最初我使用 Howler.js 播放的声音没有注册事件的正确拼写,并导致该播放所需的嵌套 Promise 出现奇怪的行为。

一切都按我的预期运行期望在 TypeScript 中可能不支持动态更改 while 循环限制,因此在当前行为中,一旦进入循环,更改计数就不会生效直到下一张幻灯片开始,因此发出下一个 while-loop。

我想我可以在六个月后阅读这个 promise.then.catch 并理解它 :) 我不知道 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);
        );
    );
  

感谢大家的建议

【讨论】:

以上是关于如何重复一系列承诺中的步骤以及如何从失败的步骤中恢复?的主要内容,如果未能解决你的问题,请参考以下文章

使用 mocha 的内置承诺支持测试失败的承诺 [重复]

如何从异步迭代器中产生一系列承诺?

如何使承诺因clojure中的错误而失败?

如何遍历 node.js 中的一系列承诺?

teamcity api如何通过casename找到build

软件工程论文书写设计步骤及如何降低重复率