如何合并GitRepository与GitCommitRef数组用于Azure DevOps扩展表格
问题
我正在用azure-devops-exstension-api创建两个数组(各自包含若干对象),一个基于内置的GitRepository接口,另一个基于内置的GitCommitRef接口。我想把这些数据放到JSX.Element表格里,单独用任意一个数组都能正常显示,但表格只能配置一个itemProvider,现在只能二选一。
我需要把两个数组的对应对象合并,以下是当前的代码:
private async initializeComponent() { const projects = await getClient(CoreRestClient).getProjects(); var repositories = [] as GitRepository[]; var lastCommits = [] as GitCommitRef []; console.log("Before Get repos") for (let i = 0; i < projects.length; i++) { const repos: GitRepository[] = await getClient(GitRestClient).getRepositories(projects[i].name); console.log(repos); repositories = repositories.concat(repos); console.log(repositories); } //Sort the list in alphabetical on repository name repositories = repositories.sort((a, b) => { return a.name.localeCompare(b.name) }); console.log("Retrieving commit Date"); //Retrieve last commit for each repo for (let i = 0; i < repositories.length; i++){ const repoName: string = repositories[i].name; const projName: string = repositories[i].project.name; console.log("Repository: " + repoName); const filter: GitQueryCommitsCriteria = { $top: 1 } console.log("Project: " + projName); console.log("Filter: " + filter); const commit: GitCommitRef[] = await getClient(GitRestClient).getCommits(repoName, filter, projName); console.log(commit); lastCommits = lastCommits.concat(commit); console.log(lastCommits); } //var fullArray = lastCommits.concat(repositories); -attempt at concat //repositories = [...lastCommits, ...repositories]; -attempt at Spread this.setState({ projects: new ArrayItemProvider(projects), gitRepos: new ArrayItemProvider(repositories), gitCommits: new ArrayItemProvider(lastCommits), nbrRepos: repositories.length }); } public render(): JSX.Element { return ( <Page className="page-pivot flex-grow"> <Header title={"Their repositories (" + this.state.nbrRepos + ")"} titleSize={TitleSize.Medium} /> <div className="git-list-pivot"> { !this.state.gitRepos && !this.state.gitCommits && <p>Loading...</p> } { this.state.gitRepos && this.state.gitCommits && <Table columns={this.state.columns} itemProvider={this.state.gitCommits} /> } </div> </Page> ); }
我试过concat、spread、push等方法都没成功。当前两个数组的结构示例:
repositories = [{name: "repo1", size: 123}, {name: "repo2", size: 456}] lastCommits = [{author: "user1", commitId: "abc123"}, {author: "user2", commitId: "def456"}]
我想要的合并结果:
finalArray = [{name: "repo1", size: 123, author: "user1", commitId: "abc123"}, {name: "repo2", size: 456, author: "user2", commitId: "def456"}]
解决方案
核心思路是按索引将两个数组的对应对象合并,因为repositories和lastCommits是一一对应的(每个仓库对应它的最新提交),所以可以用map遍历仓库数组,同时取出对应索引的提交对象,将两者的属性合并。
修改步骤
- 在获取完所有提交后,创建合并后的数组:
// 合并两个数组的对应对象,处理可能的空提交情况 const finalArray = repositories.map((repo, index) => { const commit = lastCommits[index] || {}; // 防止某个仓库无提交导致报错 return { ...repo, ...commit }; });
- 更新
setState,新增合并后的ArrayItemProvider:
this.setState({ projects: new ArrayItemProvider(projects), gitRepos: new ArrayItemProvider(repositories), gitCommits: new ArrayItemProvider(lastCommits), mergedRepoData: new ArrayItemProvider(finalArray), // 合并后的数据源 nbrRepos: repositories.length });
- 在
render中使用合并后的数据源:
{ this.state.mergedRepoData && <Table columns={this.state.columns} itemProvider={this.state.mergedRepoData} /> }
完整修改后的initializeComponent方法
private async initializeComponent() { const projects = await getClient(CoreRestClient).getProjects(); var repositories = [] as GitRepository[]; var lastCommits = [] as GitCommitRef []; // 获取所有项目下的仓库 for (let i = 0; i < projects.length; i++) { const repos: GitRepository[] = await getClient(GitRestClient).getRepositories(projects[i].name); repositories = repositories.concat(repos); } // 按仓库名称排序 repositories = repositories.sort((a, b) => a.name.localeCompare(b.name)); // 获取每个仓库的最新提交 for (let i = 0; i < repositories.length; i++){ const repoName = repositories[i].name; const projName = repositories[i].project.name; const filter: GitQueryCommitsCriteria = { $top: 1 }; const commit = await getClient(GitRestClient).getCommits(repoName, filter, projName); lastCommits = lastCommits.concat(commit); } // 合并仓库与提交数据 const finalArray = repositories.map((repo, index) => { const commit = lastCommits[index] || {}; return { ...repo, ...commit }; }); this.setState({ projects: new ArrayItemProvider(projects), gitRepos: new ArrayItemProvider(repositories), gitCommits: new ArrayItemProvider(lastCommits), mergedRepoData: new ArrayItemProvider(finalArray), nbrRepos: repositories.length }); }
说明
- 用
map遍历仓库数组时,通过index关联lastCommits中的对应提交,保证数据一一匹配。 - 添加
|| {}处理无提交的仓库,避免合并时出现undefined导致的异常。 - 合并后的对象同时包含
GitRepository和GitCommitRef的所有属性,可直接在表格列配置中使用这些属性。
内容的提问来源于stack exchange,提问作者Keebler
相关产品推荐
相关产品推荐

