Typescript Promise 循环中的数据流和内存问题

Data flow and Memory problem in Typescript Promise loop

我正在做一个项目,我必须从 Azure DevOps 存储库中读取大约 3000 多个 JSON 文件,并将它们的内容存储在一个字符串中,我以后可以使用。

下面是我用来获取存储库中项目列表的方法。我不允许假定任何目录层次结构,所以我将 recursionLevel 参数设置为完整。

Link 到文档:https://docs.microsoft.com/en-us/javascript/api/azure-devops-extension-api/gitrestclient#getitems-string--string--string--versioncontrolrecursiontype--boolean--boolean--boolean--boolean--gitversiondescriptor-

function getItems(repositoryId: string, project?: string, scopePath?: string, recursionLevel?: VersionControlRecursionType, includeContentMetadata?: boolean, latestProcessedChange?: boolean, download?: boolean, includeLinks?: boolean, versionDescriptor?: GitVersionDescriptor)

上面的函数 returns Git 项目列表的 Promise 从那里我可以从存储库的根目录中获取每个文件的相对路径

获得项目列表后,我想一个一个地阅读它们并将它们的内容存储在一个字符串中。为此,我正在使用这种方法:

function getItemText(repositoryId: string, path: string, project?: string, scopePath?: string, recursionLevel?: VersionControlRecursionType, includeContentMetadata?: boolean, latestProcessedChange?: boolean, download?: boolean, versionDescriptor?: GitVersionDescriptor, includeContent?: boolean, resolveLfs?: boolean)

这个功能在我之前分享的 link 中也可用。你必须向下滚动一点。 它returns内容为字符串的Promise。

我读取所有文件的代码:

AdoClient.getInstance().getItems(this.repoID, this.projectName, this.commonData.inputBranchName).then(data=>{
            data.forEach(element => {
                if(element.gitObjectType==3)
                {
                   AdoClient.getInstance().getItemText(this.repoID,element.path,this.commonData.inputBranchName).then(element=>{ content.concat(element);
});})});

在上面的代码中:

  1. gitObjectType=3 表示一个文件
  2. 你看到的函数getItems()和getItemText()其实就是我的函数。我写了一个定义来传递 3 个必需的参数。在 AdoClient 文件中,我使用 GitRestClient 对象对函数进行了原始调用,就像您在文档中所做的那样。

这是 AdoClient 文件中的原始函数调用:

public async getItemText(repoId: string, filePath: string, branchName: string) {
        return this.gitClient.then(client => client.getItemText(repoId, filePath, null, null, 'none', false, false, false, {version: branchName, versionOptions: 0, versionType: 0}));
    }

public async getItems(repositoryId: string, project: string,branch: string){
        return this.gitClient.then(client=>client.getItems(repositoryId, project, "/ServiceGroupRoot/", 'full', true, false, false, true, {version: branch, versionOptions: 0, versionType: 0}));
    }

另请注意 /ServiceGroupRoot/ 是我存储库中的根目录。

当我这样做时,我无法获取内容变量中的所有内容,而且 Google chrome 由于 3000+ [=46] 而显示 ERR_INSUFFICIENT_RESOURCES =] 同时调用。这个错误不会出现在 Mozilla 中。但是在 Mozilla 中,当我打印内容时它显示空字符串。我想要的是一种对我的执行步骤进行排序的方法,以便我可以在我的内容字符串中包含所有内容。有没有办法 运行 Promise 调用的循环并让它们一个一个地执行?一个接一个,我的意思是完成一个然后开始下一个,而不是一次加载所有内容,或者我必须遵循其他方法吗?

我想最简单的方法就是使用带有 await 的 for 循环:

const work = i => {
  return new Promise(resolve => {
    setTimeout(() => resolve(i), Math.floor(Math.random() * 100));
  });
};

const array = Array(10).fill(0).map((_, i) => i + 1);

// non sequencial
const test_then = () => {
  array.forEach(i => {
    work(i).then(i => {
      console.log(i);
    });
  });
};

// sequencial
const test_await = async () => {
  for (let i = 0; i < array.length; i++) {
    console.log(await work(i));
  }
};

test_then();
test_await();

代码中存在一些严重错误。

建议使用传统的 for 循环,以便我们可以使用异步等待语法。

我不知道资源部分,但我在下面粘贴了一个清晰的代码。

async function main() {
let content = '';
const data = await AdoClient.getInstance().getItems(/* pass params here*/);
for (let i = 0; i < data.length; i++) {
  if(data[i].gitObjectType==3){
   const result = await AdoClient.getInstance().getItemText(/* pass params here*/); 
   content.concat(result);
  }
}

return content;
} // main close


const c = main();
console.log(c);// your output