【问题标题】:Async is out of sync异步不同步
【发布时间】:2021-04-29 18:05:24
【问题描述】:

我有一个按钮,点击后会生成一个 http.get,然后显示一些数据,尽管我的 async/await 似乎没有正确同步。

由于我还没有完全弄清楚的原因,this.tabRows = file.contents 将在 loadDateFolderFileContents() 完成之前被调用。我在某处错过了await 吗?

  async ngAfterViewInit() {
    if (!this.drawn) {
        if(!file.contents){
          await this.dataLakeService.loadDateFolderFileContents(file.parentFolder);
        }
        this.tabRows = file.contents;
        this.redraw();
    }
  }

  public async loadDateFolderFileContents(dateFolder: folder) {
    await date.files.map(async file => {
      file.contents = await this.getFileContents(dateFolder.name, file.name);
    });
  }

  public async loadDateFolderFileContents(dateName: string, fileName: string): Promise<any> {
    var url = this.buildUrl(dateName, fileName);
    var fileContents = {};
    await this.http.get<any>(url).toPromise()
      .then(contents => { 
        fileContents = contents; 
      })
      .catch(e => { 
        console.log(`Error retreiving file contents from url ${url}. Exception:${e}`); 
      });
    return fileContents;
  }

【问题讨论】:

  • 这个:return fileContents; --> 这能回答你的问题吗? How do I return the response from an asynchronous call?
  • 这很奇怪,你正在等待,但你有一个 .then 不会被等待。只需让 content = await this.http.get .... 并将其放入 try catch
  • @KeithNicholas 感谢您的提示。我对 JS/TS + Promises 的整个世界还是陌生的,所以我仍然在这里和那里挣扎。

标签: javascript angular typescript asynchronous


【解决方案1】:

map 不是异步的,所以不是:

await date.files.map(async file => {
...

试试

await Promise.all(date.files.map(async file => {
...)

【讨论】:

    【解决方案2】:

    如果你在 map 中使用 await,map 将总是返回一个 promise 数组。这是因为异步函数总是返回 Promise。
    由于 map 总是返回 Promise(如果你使用 await),你必须等待 Promise 数组得到解决。你可以用 await Promise.all(arrayOfPromises) 来做到这一点,在所有的 Promise 都解决之后,Promise.all 返回一个 Promise。
    以下是您更新的代码

    async ngAfterViewInit() {
        if (!this.drawn) {
            if(!file.contents){
              await this.dataLakeService.loadDateFolderFileContents(file.parentFolder);
            }
            this.tabRows = file.contents;
            this.redraw();
        }
      }
    
      public async loadDateFolderFileContents(dateFolder: folder) {
        await Promise.all(date.files.map(async file => {
          file.contents = await this.getFileContents(dateFolder.name, file.name);
        }));
      }
    
      public async loadDateFolderFileContents(dateName: string, fileName: string): Promise<any> {
        var url = this.buildUrl(dateName, fileName);
        var fileContents = {};
        await this.http.get<any>(url).toPromise()
          .then(contents => { 
            fileContents = contents; 
          })
          .catch(e => { 
            console.log(`Error retreiving file contents from url ${url}. Exception:${e}`); 
          });
        return fileContents;
      }
    

    【讨论】:

    • 我需要从 loadDateFolderFileContents() 返回吗?
    • @ChrisPhillips,这是你的选择,没关系,因为异步函数返回它自己的未定义值,包装在承诺中,如果你不从中返回任何东西,否则无论你返回什么,我们在这里已经在 async 函数中使用 await,所以函数只会在异步任务完成后返回
    • @ChrisPhillips 让我知道它是否有效
    • 谢谢,这是正确的答案(就像下面的其他人一样!)。我会早点标记它,但我要出去过夜。
    【解决方案3】:

    我认为这就是你想要做的:

    async ngAfterViewInit() {
        if (!this.drawn) {
            if(!file.contents){
              await this.dataLakeService.loadDateFolderFileContents(file.parentFolder);
            }
            this.tabRows = file.contents;
            this.redraw();
        }
      }
    
      public async loadDateFolderFileContents(dateFolder: folder) {
        await Promise.allSettled(date.files.map(async file => {
          file.contents = await this.getFileContents(dateFolder.name, file.name);
          return file;
        }));
      }
    
      public async loadDateFolderFileContents(dateName: string, fileName: string): Promise<any> {
        var url = this.buildUrl(dateName, fileName);
        var fileContents = {};
         
        try { 
            const contents = await this.http.get<any>(url).toPromise();
            fileContents = contents; 
            return fileContents;
          } catch(e){
              console.log(`Error retreiving file contents from url ${url}. Exception:${e}`);
          }
     
        
      }
    

    【讨论】:

      猜你喜欢
      • 2020-08-01
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-11
      • 2014-04-02
      相关资源
      最近更新 更多