Преодолеть ожидающие обещания и завершить сборку JSON в Node.js с помощью Axios

1

Я пытаюсь создать JSON файл, выполнив последовательные HTTP requests с помощью Axios:

  1. Получить массив объектов (проектов)
  2. Создайте свойство массива в каждом проекте с заданными задачами
  3. Получать каждый проект
  4. Нажимайте каждый проект в свой объект task (т.е. заполняйте этот массив в каждом объекте проекта)
  5. Создайте файл 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 и, наконец, добавить недостающие данные.

Что мне нужно сделать?

Теги:
promise
axios

2 ответа

0

Вы можете попробовать асинхронное ожидание синтаксиса для написания асинхронного кода, например, синхронного с использованием обещаний. Это может быть просто понять и выполнить обещание. пример:

Мы могли бы перезаписать функцию 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 || [];
}
0

Проблема в том, что 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 обработчика .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), а не отклонять, что, вероятно, не то, что вы хотите - вы можете найти поток управления легче обрабатывать, если вы поймаете ошибки в вызывающем элементе функции:

return Promise.all(taskPromises)
  .then(() => projects);
  .catch((err) => {
    console.log(err);
  });

Что - то еще отметить, что .then, такие как

.then(response => { return response } )

полностью лишнее - существующее Promise уже решает response. Помещение другого Promise в конец, которое берет вход и выводит его снова, ничего полезного не делает - не стесняйтесь полностью отказаться от этого.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню