使用 Axios 在 Node.js 中克服 Pending Promise 并完成构建 JSON
Posted
技术标签:
【中文标题】使用 Axios 在 Node.js 中克服 Pending Promise 并完成构建 JSON【英文标题】:Overcome Pending Promise and Finish Building JSON in Node.js with Axios 【发布时间】:2019-04-06 06:58:30 【问题描述】:我正在尝试通过连续使用HTTP requests
和Axios
来构建JSON
文件:
-
获取对象(项目)数组
在每个名为 tasks 的项目中创建一个数组属性
获取每个项目的任务
将每个项目的任务推送到其任务属性中(即在每个项目对象中填充该数组)
从修改后的项目数组中创建一个
JSON
文件
代码:
let getProjects = function()
try
return axios.get('https://app.asana.com/api/1.0/projects/').then(response => return response )
catch (error)
console.error(error)
let getTasks = function(project)
try
return axios.get('https://app.asana.com/api/1.0/projects/'+project+'/tasks').then(response => return response )
catch (error)
console.error(error)
function getAsanaData()
return getProjects()
.then(function(result)
let projects = []
for(let project of result.data.data)
project.tasks = []
project.tasks.push(getTasks(project.gid))
projects.push(project)
return projects;
)
Promise.try(() =>
return getAsanaData();
).then((result) =>
console.log(util.inspect(result, showHidden: false, depth: null))
var asanaData = JSON.stringify(result);
fs.writeFile("thing.json", asanaData);
);
日志结果是这样的:
[ id: 35534235917762,
gid: '35534235917762',
name: 'History+',
resource_type: 'project',
tasks: [ Promise <pending> ] ,
id: 35583453238038,
gid: '35583453238038',
name: 'NRG - AccountingSeed Phase 2',
resource_type: 'project',
tasks: [ Promise <pending> ] ,
]
注意Promise <pending>
的持久化。
JSON 是这样的:
[
"id": 35534235917762,
"gid": "35534235917762",
"name": "History+",
"resource_type": "project",
"tasks": [
]
,
"id": 35583453238038,
"gid": "35583453238038",
"name": "NRG - AccountingSeed Phase 2",
"resource_type": "project",
"tasks": [
]
]
注意空任务属性。
似乎我已经非常接近完成一个完整的JSON
,但我花了很多时间试图通过待处理的promise
并最终添加缺失的数据。
我需要做什么?
【问题讨论】:
【参考方案1】:问题在于getTasks
是异步的,因此在for
循环中简单地调用getTasks
不会等待Promise 解决。要等待它们全部解决,请在这些 Promise 的数组上使用 Promise.all
,然后当 that 解决时,您可以将结果分配给 project.tasks
:
function getAsanaData()
return getProjects()
.then((result) =>
const projects = result.data.data;
const taskPromises = projects.map((project) =>
return getTasks(project.gid)
.then((task) =>
project.tasks = [task];
);
);
return Promise.all(taskPromises)
.then(() => projects);
);
另请注意,被拒绝的 Promise
不会被捕获在 try
/ catch
块内:
try
new Promise((_, reject) => setTimeout(reject, 1000))
catch(e)
console.log('error caught');
代替try/catch
,捕获Promise
错误(当您不使用await
时)的正确方法是在Promise
链的末尾链接.catch
处理程序:
const getProjects = function()
return axios.get('https://app.asana.com/api/1.0/projects/')
.catch((error) => console.error(error));
但是 还有一点需要注意的是 完全是多余的——现有的.catch
导致Promise
链解析,而不是拒绝,这意味着当函数被调用时,得到的Promise
将解析为一个值 (undefined
) 而不是拒绝,这可能不是您想要的 - 如果您在函数的 调用者 中捕获错误,您可能会发现控制流更容易处理:
return Promise.all(taskPromises)
.then(() => projects);
.catch((err) =>
console.log(err);
);
.then
比如.then(response => return response )
Promise
已经解析为response
。将另一个Promise
链接到最后,它接收输入并再次输出它并没有做任何有用的事情 - 随意完全关闭它。
【讨论】:
【参考方案2】:您可以尝试使用 async await 语法来编写异步代码,例如使用 Promise 进行同步。 理解并遵循完整的承诺可能很简单。 示例:
我们可以像这样覆盖你的 getProject 函数:
let getProjects = async function()
let projectsResponse;
try
projectsResponse =
axios.get('https://app.asana.com/api/1.0/projects/');
catch (error)
console.error(error)
return projectsResponse && projectsResponse.data || [];
【讨论】:
以上是关于使用 Axios 在 Node.js 中克服 Pending Promise 并完成构建 JSON的主要内容,如果未能解决你的问题,请参考以下文章
如何在 node.js 中使用 axios 循环许多 http 请求
反应 js:axios 向 node.js api 发布请求