亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在一個承諾中獲取來自不同數組的結果。

在一個承諾中獲取來自不同數組的結果。

喵喵時光機 2022-09-29 15:26:27
我正在為蓋茨比制作一個自定義源代碼插件,它將從GitHub存儲庫中獲取降價文件。存儲庫具有單個文件(blob)和文件夾(樹),它們又包含文件。我需要將所有文件(包括文件夾中的文件)放在一個中,但我不知道如何做到這一點。我已經設法從存儲庫中獲取單個文件,并且我有一個函數,該函數從樹中返回一個文件數組。但我不知道如何將它們結合起來。Promise.all這是我的代碼。圖形 QL 查詢以獲取存儲庫、樹和文件信息:const repositoryQuery = `{  viewer {    repository(name: "repository-name") {      object(expression: "master:") {        ... on Tree {          entries {            name            oid            type          }        }      }    }  }}`const treeQuery = `  query getTree($id: GitObjectID!) {    viewer {      repository(name: "repository-name") {        object(oid: $id) {          ... on Tree {            entries {              name              oid              type            }          }        }      }    }  }`const fileQuery = `  query getFile($id: GitObjectID!) {    viewer {      repository(name: "repository-name") {        object(oid: $id) {          ... on Blob {            text          }        }      }    }  }` 以及函數本身:const data = await client.request(repositoryQuery)const getTree = async entry => {  const data = await client.request(treeQuery, { id: entry.oid })  const array = await data.viewer.repository.object.entries  return array}const getFile = async entry => {  const data = await client.request(fileQuery, { id: entry.oid })  const result = await data.viewer.repository.object  return result}const files = await Promise.all(  data.viewer.repository.object.entries    .filter(entry => entry.type !== "tree")    .map(entry => {      return (        getFile(entry)        .then(file => {          return {            data: file.text          }        })      )    }  ))files.forEach(file =>  createNode({...}))如何更新,以便:const files運行 ,如果getFile()entry.type !== "tree"如果是 ,則在樹中獲取一個文件數組,然后為每個文件運行。entry.typetreegetTree()getFile()將所有結果合并到一個數組中,以便我可以應用于它們 。createNode我非常感謝您的幫助。
查看完整描述

2 回答

?
倚天杖

TA貢獻1828條經驗 獲得超3個贊

您可以從用于遞歸遍歷目錄的 walk 函數中獲得一些靈感。從那里。它看起來像這樣:

async function walk(entry, isRoot) {

  if (isRoot){

    return await processEntry(entry);

  }

  let files = await getTreeEntryFromTree(repository, entry.oid);

  files = await Promise.all(files.data.viewer.repository.object.entries.map(async file => {

    return await processEntry(file);

  }));

  return files.reduce((all, folderContents) => all.concat(folderContents), []);

}


async function processEntry(entry){

  if (entry.type === "tree") {

    return walk(entry, false); 

  } else {

    let res = await getBlob(repository, entry.oid);

    return [{

      name: entry.name,

      oid: entry.oid,

      data:res.data.viewer.repository.object.text

    }];

  }

}

因此,它只是將目錄替換為樹,并在返回文件時請求每個文件的數據內容。


源插件的以下代碼(不含 ) :gatsby-node.jscreateSchemaCustomization


const { ApolloClient } = require("apollo-client")

const { InMemoryCache } = require("apollo-cache-inmemory")

const { HttpLink } = require("apollo-link-http")

const fetch = require("node-fetch")

const gql = require("graphql-tag")

const { setContext } = require('apollo-link-context');


const token = "YOUR_TOKEN";

const repository = "YOUR_REPO";


const authLink = setContext((_, { headers }) => {

  return {

    headers: {

      ...headers,

      authorization: token ? `Bearer ${token}` : null,

    }

  }

});


const defaultOptions = {

  watchQuery: {

    fetchPolicy: 'no-cache',

    errorPolicy: 'ignore',

  },

  query: {

    fetchPolicy: 'no-cache',

    errorPolicy: 'all',

  },

}


const client = new ApolloClient({

  link: authLink.concat(new HttpLink({ uri: 'https://api.github.com/graphql', fetch: fetch  })),

  cache: new InMemoryCache(),

  defaultOptions: defaultOptions,

});


exports.sourceNodes = async function sourceNodes(

  {

    actions,

    cache,

    createContentDigest,

    createNodeId,

    getNodesByType,

    getNode,

  },

  pluginOptions

) {

  const { createNode, touchNode, deleteNode } = actions

  const { data } = await getTreeFromRepo(repository)


  let sourceData = data;


  fileArr = []

  sourceData.viewer.repository.object.entries.map(it => {

    fileArr.push(walk(it, true))

  });

  let res = await Promise.all(fileArr)

  let result = res.flat();

  console.log(result);

  console.log(`got ${result.length} results`);

  return

}


async function walk(entry, isRoot) {

  if (isRoot){

    return await processEntry(entry);

  }

  let files = await getTreeEntryFromTree(repository, entry.oid);

  files = await Promise.all(files.data.viewer.repository.object.entries.map(async file => {

    return await processEntry(file);

  }));

  return files.reduce((all, folderContents) => all.concat(folderContents), []);

}


async function processEntry(entry){

  if (entry.type === "tree") {

    return walk(entry, false); 

  } else {

    let res = await getBlob(repository, entry.oid);

    return [{

      name: entry.name,

      oid: entry.oid,

      data:res.data.viewer.repository.object.text

    }];

  }

}


async function getTreeFromRepo(repo) {

    return await client.query({

      query: gql`

        query {

          viewer {

            repository(name: "${repo}") {

              object(expression: "master:") {

                ... on Tree {

                  entries {

                    name

                    oid

                    type

                  }

                }

              }

            }

          }

        }

      `,

    })

}


async function getTreeEntryFromTree(repo, oid) {

  return await client.query({

    query: gql`

      query getTree($id: GitObjectID!) {

        viewer {

          repository(name: "${repo}") {

            object(oid: $id) {

              ... on Tree {

                entries {

                  name

                  oid

                  type

                }

              }

            }

          }

        }

      }

    `,

    variables: {

      id: oid

    }

  })

}


async function getBlob(repo, oid){

  return await client.query({

    query: gql`

      query getFile($id: GitObjectID!) {

        viewer {

          repository(name: "${repo}") {

            object(oid: $id) {

              ... on Blob {

                text

              }

            }

          }

        }

      }

    `,

    variables: {

      id: oid

    }

  })

}

您需要在上面的代碼中替換 Github 令牌和存儲庫名稱。


它返回一個包含文件內容、名稱和 oid 的對象數組


請注意,使用二進制文件的返回:... on Blob { text }null


文本(字符串)UTF8 文本數據,如果 Blob 是二進制的,則為空


此外,還可以使用 Github API v3 在單個調用中以遞歸方式遍歷樹,從而大大減少了請求數。你會有這樣的東西:


async function getAllEntries(repo, owner){

  return fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees/master?recursive=1`,{

    headers: {

      'Authorization': `Bearer ${token}`,

    }

  })

  .then(response => response.json());

}

完整示例(對于蓋茨比源代碼插件):


const { ApolloClient } = require("apollo-client")

const { InMemoryCache } = require("apollo-cache-inmemory")

const { HttpLink } = require("apollo-link-http")

const fetch = require("node-fetch")

const gql = require("graphql-tag")

const { setContext } = require('apollo-link-context');


const token = "YOUR_TOKEN";

const repository = "YOUR_REPO";

const owner = "YOUR_LOGIN";


const authLink = setContext((_, { headers }) => {

  return {

    headers: {

      ...headers,

      authorization: token ? `Bearer ${token}` : null,

    }

  }

});


const defaultOptions = {

  watchQuery: {

    fetchPolicy: 'no-cache',

    errorPolicy: 'ignore',

  },

  query: {

    fetchPolicy: 'no-cache',

    errorPolicy: 'all',

  },

}


const client = new ApolloClient({

  link: authLink.concat(new HttpLink({ uri: 'https://api.github.com/graphql', fetch: fetch  })),

  cache: new InMemoryCache(),

  defaultOptions: defaultOptions,

});


exports.sourceNodes = async function sourceNodes(

  {

    actions,

    cache,

    createContentDigest,

    createNodeId,

    getNodesByType,

    getNode,

  },

  pluginOptions

) {

  const { createNode, touchNode, deleteNode } = actions

  const { tree } = await getAllEntries(repository, owner)

  fileArr = []

  tree.map(it => {

    fileArr.push(walk(it, true))

  });

  let res = await Promise.all(fileArr)

  let result = res.filter(value => Object.keys(value).length !== 0);

  console.log(result);

  console.log(`got ${result.length} results`);

  return

}


async function walk(entry){

  if (entry.type === "blob") {

    let res = await getBlob(repository, entry.sha);

    return {

      name: entry.path,

      oid: entry.sha,

      data: res.data.viewer.repository.object.text

    };

  }

  return {};

}


async function getAllEntries(repo, owner){

  return fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees/master?recursive=1`,{

    headers: {

      'Authorization': `Bearer ${token}`,

    }

  })

  .then(response => response.json());

}


async function getBlob(repo, oid){

  return await client.query({

    query: gql`

      query getFile($id: GitObjectID!) {

        viewer {

          repository(name: "${repo}") {

            object(oid: $id) {

              ... on Blob {

                text

              }

            }

          }

        }

      }

    `,

    variables: {

      id: oid

    }

  })

}

如果您需要不惜一切代價獲取二進制內容,則需要使用Github API v3,它直接在獲取樹結果中提供內容URL。內容 URL 返回以 base64 編碼的內容,請參閱此文件。


因此,如果您想要base64編碼的內容(二進制+文本),您將擁有以下內容(對于源插件):gatsby-node.js


const fetch = require("node-fetch")


const token = "YOUR_TOKEN";

const repository = "YOUR_REPO";

const owner = "YOUR_LOGIN";


exports.sourceNodes = async function sourceNodes(

  {

    actions,

    cache,

    createContentDigest,

    createNodeId,

    getNodesByType,

    getNode,

  },

  pluginOptions

) {

  const { createNode, touchNode, deleteNode } = actions

  const { tree } = await getAllEntries(repository, owner)

  fileArr = []

  tree.map(it => {

    fileArr.push(walk(it, true))

  });

  let res = await Promise.all(fileArr)

  console.log(res);

  console.log(`got ${res.length} results`);

  return

}


async function walk(entry){

  if (entry.type === "blob") {

    let res = await getBlob(entry.url);

    return {

      name: entry.path,

      oid: entry.sha,

      data: res.content

    };

  }

  return {};

}


async function getAllEntries(repo, owner){

  return fetch(`https://api.github.com/repos/${owner}/${repo}/git/trees/master?recursive=1`, {

    headers: {

      'Authorization': `Bearer ${token}`,

    }

  })

  .then(response => response.json());

}


async function getBlob(url){

  return fetch(url, {

    headers: {

      'Authorization': `Bearer ${token}`,

    }

  })

  .then(response => response.json());

}


查看完整回答
反對 回復 2022-09-29
?
子衿沉夜

TA貢獻1828條經驗 獲得超3個贊

首先,您可以遍歷每棵樹,然后為每個樹獲取一個文件數組,這將為您提供一個二維數組:


.map(async entry => {

  const files = await getTree(entry);

  return Promise.all(

    files.map(file => getFile(file).then(fileRes => ({ data: fileRes.text })))

  );

)

然后,您需要拼合結果,使其成為一個單維數組:


const files = allFiles.flat();

我希望我正確地理解了你的問題;結果是一個單維的文件數組(即 ),而不是一個多維數組(即 )。getTree()[file1, file2, file3][[file1, file2], [[file1, file2], [file1]], file1, file2]


查看完整回答
反對 回復 2022-09-29
  • 2 回答
  • 0 關注
  • 110 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號