TypeScript:使用Promise.all替换图片源时的行为不一致

问题描述

对于我的SPFx Webpart(使用React / TypeScript),我试图替换某些图像的源,因为必须首先使用另一个Microsoft Graph API调用来检索最初获取的源。

我获取HTML内的所有图像,稍后将使用temporalDivElement.querySelectorAll("img")呈现这些图像,然后检查它们是否需要替换源。如果是这种情况,那么我将调用Graph API来获取新的图像源(如果无法获取图像,则调用一个替换跨度节点)。由于必须遍历所有图像,因此我首先将所有这些请求收集到Promises数组中的Graph API中,然后再使用Promise.all()执行它们。

这是我当前的代码:

  public parseAndFixBodyContent(messageId: string,bodyContent: string) {
    return new Promise<string>(async (resolve,reject) => {
      let temporalDivElement = document.createElement("div");
      temporalDivElement.innerHTML = bodyContent;
      // For hosted content images: fetch hosted content with Graph API,convert to BLOB and then replace existing src attribute with BLOB value
      const imgTags = temporalDivElement.querySelectorAll("img");
      const hostedImagesReplacementPromises: Promise<void>[] = [];
      imgTags.forEach((img) => {
        if (img.src &&
          img.src.indexOf(`/messages/${messageId}/hostedContents/`) > -1) {
            // Hosted Content url found,try to fetch image through API
            let hostedContentApiUrl: string = img.src;
            hostedImagesReplacementPromises.push(this.replaceHostedContentImageSource(hostedContentApiUrl,img));
          }
      });

      Promise.all(hostedImagesReplacementPromises)
      .then(() => {
        resolve(temporalDivElement.innerHTML);
      });
    });
  }

  public replaceHostedContentImageSource(hostedContentApiUrl: string,image: HTMLImageElement) {
    return new Promise<void>(async (resolve,reject) => {
      this.getHostedContentAsBlob(hostedContentApiUrl).then((imageBlobUrl) => {
        image.src = imageBlobUrl;
        resolve();
      })
      .catch(error => {
        // We could not fetch the hosted content for the image
        let missingImageInfo = document.createElement("span");
        missingImageInfo.innerText = `(${strings.ImageNotAvailable})`;
        image.parentNode.replaceChild(missingImageInfo,image);
        resolve();
      });
    });
  }
  
  public getHostedContentAsBlob(hostedContentApiUrl: string) {
    return new Promise<string>(async (resolve,reject) => {
      this.context.msGraphClientFactory
        .getClient()
        .then((client: MSGraphClient): void =>{
          client
            .api(hostedContentApiUrl)
            .version("beta")
            .responseType('blob')
            .get((error,response: Blob,rawResponse?: any) => {
              if (rawResponse.status == 200 && response) {
                const imageUrl: string = URL.createObjectURL(response);
                resolve(imageUrl);
              } else {
                reject(new Error(strings.ErrorCouldNotGetHostedConent));
              }
            });
          })
        .catch(error => {
          reject(error);
        });
    });
  }

此代码有时有效,有时根本无效,有时对一半图像有效,而对另一半图像无效。例如,我在托管内容图像的两个通道回复中都使用了它,有时我会同时获得两个图像,然后我只获得一个图像,而另一个图像则完全没有被替换(甚至连带有替换失败的信息)或两者均未处理。就像有时候诺言没有得到执行,或者至少在渲染之前的正确时间没有实现。

我看不到代码有什么问题,但我想这里存在一些计时问题?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)