链接 fetch, fetch, map, filter, fetch, fetch

Chaining fetch, fetch, map, filter, fetch, fetch

我的问题有何不同: 在我成功链接 promise 后,我留下了单独的数组列表文件和目录,需要再次获取这些目录中的文件,将其添加到第一个文件列表,然后最后根据所有完整的文件列表获取。

每个函数(包括未显示的另一个函数)都可以进入目录并列出其中的文件。

归根结底,我只需要我所有 github 存储库中我拥有的任何 package.json 文件的内容,如果我要这样做 long/wrong 方式。

我确实尝试过return一个对象

{
files: files,
paths: paths
}

但对象每次都是空的。

listRepos = async () => {
    const path = '/user/repos'
    return fetch(api + path, options)
    .then(res => res.json())
    .then(json => json.filter(repo => {
        return repo.owner.login === user
    }))
}

listContents = async (repo) => {
    const path = `/repos/${repo.owner.login}/${repo.name}/contents`
    return fetch(api + path, options)
    .then(res => res.json())
}

getNext = async () => {
    let contents = []
    let repoList = await listRepos()
    return repoList.map(async (repo) => {
        await listContents(repo).then(async (contents) => { // This happens for each repo
            let pathList = await contents.filter(entry => {
                return entry.type === 'dir' && entry.name != 'node_modules'
            })
            pathList.forEach(path => paths.push(path))
            let fileList = await contents.data.filter(entry => {
                return entry.name === 'package.json'
            })
        })
        return {
            files: fileList,
            paths: pathList
        }
    })
}

我在

Promise { <pending> }

或"Unhandled Promise Rejection"的

我确实意识到我需要捕获所有错误,为了 space 和可读性,我从代码中删除了这些错误。

你得到了很多 Promise { <pending> } 因为你正在将你的 repoList 映射到 promises :

return repoList.map(async (repo) => {

异步函数总是return 一个承诺。你想要那些承诺解决的价值。您可以使用 Promise.all:

获取承诺数组的值
Promise.all([promise, promise]).then(values => console.log(values)
// ['foo', 'bar']

所以你有一个回购列表,然后你将这个列表映射到承诺,然后你必须将它映射回已解决的值:

const values = await Promise.all(['foo', 'bar'].map(val => fetchSomething(val)))

你的情况:

return Promise.all(repoList.map(async (repo) => {
    ...
}));

Promise.all return是一个承诺,所以记得使用await getNext()


在您的 repoList 映射函数内,您在 listContents 映射函数范围内声明 let pathListlet fileList,然后尝试从 repoList 映射函数范围访问它们。你可能想直接 return 它们,像这样:

getNext = async () => {
    let contents = []
    let repoList = await listRepos()
    return repoList.map((repo) => {
        return listContents(repo).then(async (contents) => { // This happens for each repo
            let pathList = await contents.filter(entry => {
                return entry.type === 'dir' && entry.name != 'node_modules'
            })
            pathList.forEach(path => paths.push(path))
            let fileList = await contents.data.filter(entry => {
                return entry.name === 'package.json'
            })
            return {
                files: fileList,
                paths: pathList
            }
        })
    })
}

正如@ezakto 已经指出的那样,您的函数 returns 是对一系列承诺的承诺。添加 Promise.all 调用以获得对结果数组的承诺。还可以通过在可以使用 await 的地方不使用 then 来简化 async 函数(并将 awaits 放在 filtered 数组上 - 中没有任何异步内容那里):

async function getNext() {
    let repoList = await listRepos()
    return Promise.all(repoList.map(async repo => {
        const contents = await listContents(repo);
        const pathList = contents.filter(entry => {
            return entry.type === 'dir' && entry.name != 'node_modules'
        })
        // paths.push(...pathList)
        const fileList = contents.data.filter(entry => {
            return entry.name === 'package.json'
        })
        return {
            files: fileList,
            paths: pathList
        }
    }))
}