调用函数时异步等待不起作用

Posted

技术标签:

【中文标题】调用函数时异步等待不起作用【英文标题】:Async wait is not working when calling a function 【发布时间】:2021-06-14 13:33:54 【问题描述】:
var value = await this.upload();
if (value == true) 
  this.item.photos = this.uploaded;
  this.item.price = null;
  this.item.qty = null;
  this.dataSrv.addItem(this.item)
    .then(() => 
      this.dataSrv.stopLoading();
      this.dataSrv.toast('Item Added Successfully');
      this.item =  as Item;
      this.pictures = ['', '', '', ''];
      this.uploaded = [];
      this.photos = ['', '', '', ''];
    )
    .catch(err => 
      this.dataSrv.stopLoading();
      this.dataSrv.toast('Error While Adding Item. Try Again Later');
      console.log(err);
    );

在上面的代码中,我正在调用上传函数将图片上传到谷歌存储,我正在等待,所以我可以将图片链接添加到上传的数组中,这会将其保存到 this.item.photos 但它不会等待,而是直接执行真实条件。

async upload(image?) 
  var counter = 0;
  this.pictures.forEach(i => 
    if (i != '') 
      let temp: string = (i) as string;
      temp = temp.replace("data:image/jpg;base64, ", '');
      temp = temp.replace("data:image/jpg;base64,", '');
      temp = temp.replace('must use [property]=binding:', '');
      temp = temp.replace('SafeValue', '');
      temp = temp.replace('(see https://g.co/ng/security#xss)', '');
      const randomId = Math.random().toString(36) + Math.random().toString(36) + Math.random().toString(36) + Math.random().toString(36);
      const uploadTask = this.storage.ref('items/').child(randomId).putString(temp, 'base64', 
        contentType: 'image/png'
      );
      uploadTask
        .then(response => 
          console.log("uploaded");
          console.log(response);
          this.storage.ref('items/' + randomId).getDownloadURL().subscribe(url => 
            this.uploaded.push(url);
            counter++;
          );
        )
        .catch(err => 
          console.log('not uploaded');
        );
    
  );
  if (counter != this.uploaded.length) 
    return false;
   else 
    return true;
  

我尝试在上传函数中返回 Promise 类型,但没有任何改变 我也尝试在函数调用之后执行 then 但同样的问题发生了

注意图片数组包含base64图片

【问题讨论】:

我认为你应该在 upload 函数中返回一个承诺。否则你不会等待uploadTask 终止。 我已经尝试将它作为异步上传(图片?):Promise 但它仍然没有等待 它似乎返回了一个uploadTask,这不是一个承诺,你必须将它包装在一个承诺中。 :See here 【参考方案1】:

async 函数不会自己阻塞。问题是forEach 是同步调用的,但它包含的代码将异步运行。

这样做的常见模式:

async upload(image) 
  // use .map instead of .forEach
  // from the callback function we return a Promise, so the result would be
  // an array of promises
  const promises = this.pictures.map(i => 
    // your logic here
    // you must return the promise
    return uploadTask
        .then(response =>  /* ... */ )
        .catch(() =>  /* ... */ );
  )

  // Wait for all promises to be resolved.
  // Note for the future: Promise.all will reject if at least 1 promise rejects.
  // Your code seems to handle this case and converts a failed Promise into a success inside of `.catch` above.
  await Promise.all(promises);

  // here, the counter should be correct

【讨论】:

你确定Promise.all 可以处理promise 以外的对象吗? (一个 then-able 对象就足够了?) @XouDo Promise.all 以神秘的方式工作 :) - 在您的浏览器控制台中尝试:Promise.all([1,2]).then(result => console.log(result))。它将记录[1, 2]。这些不是承诺,但Promise.all 将它们解析为成功。 你说得对,我试过了,最重要的是,它也适用于手工制作的 thenable 对象。 我仍然有同样的问题..我已经将我的代码编辑为上面的代码,我在 Promise.all(promises) 之后做了一个 then 并且它也不起作用

以上是关于调用函数时异步等待不起作用的主要内容,如果未能解决你的问题,请参考以下文章

调用服务时异步调用不起作用 - Angular 8

dottrace 异步等待支持不起作用

等待似乎不起作用,异步(nodejs)

打字稿异步/等待不起作用

Flutter:Getx Controller中的异步函数在初始化时不起作用

在useEffect中创建一个异步函数,并在函数的while循环中使用await,似乎不起作用