【问题标题】:Using the result from one API as a parameter for another and inserting both results into a JSON array使用一个 API 的结果作为另一个 API 的参数,并将两个结果插入 JSON 数组
【发布时间】:2020-12-21 20:20:32
【问题描述】:

所以我有 2 个 API:

localhost:8080/projects(给我我拥有的项目列表)

localhost:8080/tasks/{projectid}(给我与我用作参数的项目 ID 相关的任务列表)

我使用 nodejs 来获取第一个 API 的结果,然后将它们插入到 JSON 数组中,同时从同一个请求中获取每个 id 并在第二个 api 中使用它们来获取任务,最后我'd 获取这些任务并将它们插入到与项目相同的 JSON 数组中。

但是我遇到了一个问题,在完成操作后,我会尝试显示 JSON 数组,只是为了发现它只包含项目名称(这是第一个 API 的结果),而没有找到来自第二个的信息。

这是我使用的方法:

首先我做了2个方法,一个是获取项目,一个是获取任务,我在这两种方法中都使用了回调:

const projects = (callback) =>{
const url='localhost:8080/projects'
request({url,json:true},(error,{body}) =>{
    if(error){
        callback('error')
    }else{
        callback(undefined,body)
    }
})
}
const tasks = (projectid,callback) =>{
    const url='localhost:8080/tasks/'+encodeURIComponent(projectid)
    request({url,json:true},(error,{body})=>{
        if(error){
            callback('unable to find data')
        }else{
            callback(undefined,body)
=        }
    })
}

然后我使用 express 为这两种方法定义路由:

app.get('/projects',(req,res)=>{
    func.projects((error,body)=>{
    if(error){
        return res.send({
            error : error
        })
    }
  res.send(body)
    })
})


app.get('/tasks',(req,res)=>{
    func.tasks(req.query.code,(error,body)=>{
        if(error){
            return res.send({
                error : error
            })
        }
        res.send(body)
    })
})

最后,我尝试使用 Javascript 将这 2 个路由中的数据提取到一个 json 数组中,并在把手页面中显示:

fetch('/projects').then((response) => {
    response.json().then((res) => {
        if (res.error) {
            console.log(res.error)
        } else {

            data = { todo: [] }

            //insert each project into our json array
            res.forEach((project) => {
        
                data.todo.push({ id: project.id, text: project.id })
                
                //Now we'll get the tasks using the project id as argument
                fetch('/tasks?code='+encodeURIComponent(project.id)).then((response)=>{
                    response.json().then((res)=>{
                        if(res.error){
                            console.log(error)
                        } else {
                            //add each task to the same array
                            res.forEach((task) => {
                            data.todo.push({text: task.desc, parent: item.id})
                            })
                        }
                    })
                })
            })
            gantt.parse(data);
        }
    })
})

抱歉,我只是想解释所有细节。谢谢。

编辑:我的程序的目标是使用 json 文件作为甘特图的参数,这就是为什么我调用名为 gantt 的函数,当我传递 json 对象时,该函数只显示项目,但现在显示任务。

尽管当我使用 console.log 函数时,它显示我的对象确实包含任务。我认为这里的问题是该函数同时执行两个 foreach 这就是为什么它没有返回任务,因为它还没有所需的参数

【问题讨论】:

  • 你能发布你为 todos 得到的最终输出吗?
  • 抱歉,我忘了说明我现在要编辑帖子
  • 完成我添加了解释
  • 尝试使用生成器为每个项目 id 第二次调用 fetch api。这肯定会奏效。

标签: javascript node.js json express handlebars.js


【解决方案1】:

我希望你明白fetch 是异步的,这就是为什么你有一个then 块,在异步操作完成后执行代码。我以你的例子为例,然后添加了带有数字的内联 cmets,表示执行流程。

// 1. Starts execution.
fetch('/projects').then((response) => {
    response.json().then((res) => {
        if (res.error) {
            console.log(res.error)
        } else {
            // 2. Res has the list of projects.
            data = { todo: [] }

            //insert each project into our json array
            res.forEach((project) => {
        
                data.todo.push({ id: project.id, text: project.id })
                // 3. Fetch is called for each project.
                //Now we'll get the tasks using the project id as argument
                fetch('/tasks?code='+encodeURIComponent(project.id)).then((response)=>{
                    response.json().then((res)=>{
                        if(res.error){
                            console.log(error)
                        } else {
                             // 5. Data is push is to the array.
                            //add each task to the same array
                            res.forEach((task) => {
                            data.todo.push({text: task.desc, parent: item.id})
                            })
                        }
                    })
                })
            })

            // 4. parse is called.
            gantt.parse(data);
        }
    })
})

如您所见,gantt.parse(data) 在后续获取请求的数据到达之前被调用。这意味着您必须等待所有请求完成后才能调用gantt.parse(data)。你可以使用Promise.all

您还提到console.log 显示数据。那是因为console.log 通常通过引用起作用。试试console.log(JSON.stringify(data)),你会看到丢失的数据。

为了完善它,我将使用公共 API 添加一个使用 Promise.all 的示例。

fetch('https://jsonplaceholder.typicode.com/todos')
.then(response => response.json())
.then(todos => {
    // I'm just taking the first 5 todos.
    todos = todos.slice(0, 5);
    const data = {
        todos: []
    };
    const requests = [];
    todos.forEach(todo => {
        data.todos.push({
            id: todo.id,
            title: todo.title
        });
        requests.push(fetchComments(todo.id));
    });

    Promise.all(requests).then(responses => {
        console.log(data);
        // Here is where you will call gnatt.parse
    });


    function fetchComments(id) {
        return fetch(`https://jsonplaceholder.typicode.com/todos/${id}/comments`)
            .then(res => res.json()).then(comments => {
                comments.forEach(comment => {
                    data.todos.push({
                        id: comment.id,
                        parent: id
                    });
                });
            });
    }
});

【讨论】:

  • 啊我现在明白了,我知道它有问题,但我无法修复它,因为我对承诺等还很陌生,非常感谢您的澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 2012-12-16
相关资源
最近更新 更多