我正在尝试通过使用JSON
连续创建HTTP requests
来构建Axios
文件:
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
并最终添加丢失的数据。
我需要做什么?
答案 0 :(得分:1)
问题在于getTasks
是异步的,因此仅在getTasks
循环中调用for
不会等待Promises解决。要等待它们全部解决,请在这些承诺的数组上使用Promise.all
,然后在 解决时,可以将结果分配给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
的正确方法是在结束时链接.catch
处理程序Promise
链:
const getProjects = function() {
return axios.get('https://app.asana.com/api/1.0/projects/')
.catch((error) => console.error(error));
}
但是.catch
导致Promise
链解析,而不是拒绝,这意味着当调用函数时,生成的Promise
将解析为一个值(undefined
)而不是拒绝,这可能不是您想要的-如果在调用程序中发现错误,您可能会发现控制流更易于处理函数的em>代替:
return Promise.all(taskPromises)
.then(() => projects);
.catch((err) => {
console.log(err);
});
需要注意的是.then
,例如
.then(response => { return response } )
是完全多余的-现有的Promise
已经解析为response
。将另一个Promise
链接到输入并再次输出的末尾并没有任何用处-可以完全将其保留。
答案 1 :(得分:0)
您可以尝试使用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 || [];
}