代码之家  ›  专栏  ›  技术社区  ›  Meryan

如何运行一个可观察的多次并正确地计算其结果?

  •  0
  • Meryan  · 技术社区  · 4 年前

    我有一个生成JSON的可观察对象,它实际上是一个返回不同书籍文本的API。 我需要多次调用这个observable并将结果连接到 正确的顺序 .

    如果您可以提供两种解决方案,一种是并行地和顺序地运行可观察的调用,那就太好了。也许它会点亮我脑袋里的灯泡。如果它们并行运行,我需要按BookIndex顺序组织结果。

    我读过很多博客,rxjs文档,以及其他关于可观察到的和承诺的页面,但这是一个无法理解的话题,也是一个不断挣扎的根源。我也试图通过toPromise()将Observable转换为promise,但这并没有使我成功。在我在Observable上发表这篇文章之前所做的搜索中,我看到了对.concact和joinFork的提及,但是我不知道如何应用它们来导出解决方案。

    " 等待

    https://stackblitz.com/edit/ionic-k8t49r?file=pages%2Fhome%2Fhome.ts

     // uses a class member/field to build strings into it
     // can it be written to use a local then return it?
      async MessagesBuild() {
        this.Messages_ = "";
        for (let BookIndex = 0; BookIndex < 4; BookIndex++) {
          await this.RandomString(BookIndex).subscribe(data => {
            this.Messages_ += data + "\n";
            console.log(data);
          });
        }
        return this.Messages_;  // I have difficulty grasping how returns should be coded??
      }
      //
      async ShowLast() {
        alert(this.Messages);
      }
      //
      async BuildAndShow() {
        await this.MessagesBuild();
        alert(this.Messages);
      }
    

    如果我的编码是正确的

    1. 按下“ 生成和显示消息 “我会在警报中看到最后的串联字符串。
    2. 生成异步消息 “将更新绑定视图以显示最终结果,而不仅仅是第一页。

    enter image description here

    你对我有什么看法:

    1. 在这四年之后我只知道promise.then(()=>{…})以及observable.subscribe(()=>{…})完成后执行。

    2. 我学到了一种艰难的方法,随机地撒上async/await的语法糖并不能解决这个异步世界。

    --谢谢你。非常感谢你的帮助。

    我已经把@Nenad Milosavljevic的答案加入到下面的stackblitz中 https://stackblitz.com/edit/ionic-wkplkm?file=pages%2Fhome%2Fhome.ts

    生成和显示消息 “正在工作。 但是,不确定 生成异步消息 “似乎Angular无法调用返回Promise的方法,因此我添加了BuildOnly():string。 结果(角度界限)在视图中似乎没有更新。

    过来看。 https://stackblitz.com/edit/ionic-wkplkm?file=pages%2Fhome%2Fhome.ts

    更新2:

    使Nenad的解决方案更新视图的一种方法是手动触发变更检测。我从2018年挖了一条进口线:)你觉得我能像那样从我的大脑皮层后面把这些垃圾弹出来吗?。

    就像这样

    enter image description here

    特雷弗的解决方案使用ngZone.run 为了达到同样的效果(尽管我不能称之为自动角度变化检测)。

    0 回复  |  直到 4 年前
        1
  •  2
  •   NeNaD    4 年前

    async BuildAndShow() {
        await this.MessagesBuild();
        alert(this.Messages);
    }
    

    await this.MessagesBuild() 因为它不回来了 Promise (你可以,但不会有任何效果)。所以,这意味着你必须重构 this.MessagesBuild() 承诺

    this.MessagesBuild() 也不会有任何影响,因为它 this.RandomString 是一个 Observable 而不是 承诺 . 你能做的就是把它改成 承诺 toPromise() 方法。你可以创建一个 对于每个 bookData 你在等待的。之后你可以使用 Promise.all() Promises 承诺 承诺 this.Messages_ . 在那之后你可以 resolve 具有 所以它将在 BuildAndShow() .

    代码将如下链接:

    import "rxjs/add/operator/toPromise";
    
    ...
    
    MessagesBuild() {
      return new Promise((resolve, reject) => {
        let message_result = ""
        let promises = [];
        for (let BookIndex = 0; BookIndex < 4; BookIndex++) {
          promises.push(this.RandomString(BookIndex).toPromise());
        }
        Promise.all(promises).then((results) => {
          results.forEach((result) => {
            message_result = message_result + result;
          });
          resolve(message_result);
        });
      })
    }
    

    现在你可以重构了 BuildAndShow() 等待 this.MessagesBuild() this.Messages .

     async BuildAndShow() {
        let messages = await this.MessagesBuild();
        alert(messages);
      }
    

    以下是链接: https://stackblitz.com/edit/ionic-iqsqsy?file=pages%2Fhome%2Fhome.ts

        2
  •  1
  •   Trevor Kropp    4 年前

    首先,您可以使用以下方法更改MessagesBuild:

    let data = await this.RandomString(BookIndex).toPromise();
    

    因为你只能等待一个承诺。

    然后,您可以使用以下内容连接数据:

    this.ngZone.run(() => {
        this.Messages_ += data + "\n";
    });
    

    NgZone 依赖关系是导致页面更新所必需的。

    Here 这是我的解决方案。

    await