有没有一种方法可以等待另一个Observable中调用的Observable的结果?

时间:2019-07-04 12:46:25

标签: angular rxjs electron rxjs6 angular8

我目前正在尝试构建一个小应用程序来帮助我的本地角色扮演小组。他们想要的工具中有一个可编写脚本的随机化器,以便他们可以构建骰子掷骰表。不幸的是,关于需要递归调用其中带有Observable的函数,我遇到了一些麻烦。

我在这里和Reddit上浏览了几个不同的问题,涵盖了如何从Observables获取结果或等待它解决,但是我尝试过的所有解决方案在这种情况下或在父调用中都是无效代码不等孩子解决。这包括使用map,switchMap和async / await。我只是想知道是否使用Observable加载文件是否错误。

这里是完整的上下文,以防简短的示例遗漏某些内容:https://github.com/Acaeris/draconika/blob/rolltable/src/app/providers/table.service.ts

简而言之:

@Injectable()
export class TableService {
  constructor(private http: HttpClient) {}

  get(tableId: string): Observable<RollCollection> {
    return this.http.get<RollCollection>('assets/tables/' + tableId + '.json')
      .pipe(
        catchError(this.handleError)
      );
  }

  // Roll a result from a given table or sub entry.
  roll(tableId: string, entryKey: string) {
    return this.get(tableId).pipe(
      map(data => {
        output = data[entryKey];
        parts = this.findParts(output);

        parts.forEach((part: string) => {
          if (part[1].includes('.')) {
            const splitPart = part[1].split('.');

            // Roll refers to an entry in another table.
            // This needs to finish before the return...
            this.roll(splitPart[0], splitPart[1]).toPromise()
              .then(rollOutput => output = output.replace(part[0], rollOutput));

          } else {
            // Process rolls for current file.
          }
        });

        return output;
      }
    );
  }

  private findParts(entry: string) {
    const regex = /\[([a-zA-Z.]*)\]/g;
    const parts: string[] = [];
    let m;

    do {
      m = regex.exec(entry);

      if (m) {
        parts.push(m);
      }
    } while (m);

    return parts;
  }
}

当前在类似这样的组件中调用:

this.tableService.roll('heirloom').subscribe(
  data => this.output.push(data),
  error => console.log(error)
);

heirloom.json表中有一些滚动,导致对[name.format]的调用,然后应滚动[name.json]文件的“ format”条目。

我希望它做的是滚动结果并替换传家宝滚动中字符串的[name.format]部分。

this.tableService.roll('name', 'format').subscribe(
  data => this.output.push(data),
  error => console.log(error)
);

^这将成功返回一个生成的名称,并且实际上内部滚动也将产生一个名称,但是它对输出应用得太晚了,因此组件在完成之前就接收到了结果。

我现在得到的是:“传家宝是曾经属于[name.format]的头盔”,而不是“传家宝是曾经属于Lady Amberline Dawnstrider的头盔”

0 个答案:

没有答案