NodeJS Функция контроллера возвращается до завершения данных из вызова API и array.filter - PullRequest
0 голосов
/ 15 апреля 2020

Я работаю над Slackbot, который сравнивает файл ветки репо с тем же файлом в Master, который требует двух вызовов API для API bitbucket. Первый захватывает все самые последние ветви в нашем рабочем пространстве, который включает URL-адрес, который я затем могу использовать для вызова API для различия между двумя файлами:

Фрагмент из NodeJS Файл контроллера

let diffs = await axios.get('API-Call-To-BB-For-Recent-Branches', {
            headers: {
                'Authorization': `${AUTH}`
            }
        })
        
let filteredByUser = diffs.data.values.filter(element => {
            if (element.target.author.raw.includes(username)) {
                if (element.target.repository.full_name.includes("nameOfMasterBranch")) {
                    axios.get(element.target.links.diff.href, {
                        headers: {
                            'Authorization': `${AUTH}`
                        }
                    }).then(response => {
                        let clippedBranch = {
                            branch: element.name,
                            author: element.target.author.user.display_name,
                            diff: response.data
                        }
                        // Console Logging here shows the data I'm looking for
                        console.log(clippedBranch)
                        return clippedBranch
                    }).catch(error => {
                        console.log(error)
                    })
                }
            }
        })
        // Console logging Here returns an empty array.
        console.log(filteredByUser)

        // Console logging the returned value on the main server file returns a Promise<Pending>
        return filteredByUser

Что я пробовал

  1. Я пытался использовать Promise.resolve и Promise.All, чтобы исправить проблема.
  2. Выполнение второго вызова API внутри оператора for и оператора forEach
  3. Я пытался вложить обработку массива и второй вызов API внутри .then первого Вызов API для BitBucket.

Что препятствует разрешению данных во время их возврата?

Заранее спасибо за ваше время!

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

Возможно, вы захотите соединить вызовы на .filter и .map по отдельности. Это не только «сгладит» ваш код, но и должно читать немного проще. Сначала используйте фильтр, чтобы удалить ненужные элементы. Затем отобразите полученный список и верните список обещаний, которые можно передать Promise.all

. Вот что, я полагаю, вы пытаетесь сделать:

async function getBranchesByUsername(username) {
    try {
        const diffs = await axios.get("API-Call-To-BB-For-Recent-Branches", {
            headers: {
                Authorization: `${AUTH}`,
            },
        });

        const requests = diffs.data.values
            .filter(element => {
                return element.target.author.raw.includes(username) &&
                    element.target.repository.full_name.includes("nameOfMasterBranch")
            })
            .map(element => {
                return axios
                    .get(element.target.links.diff.href, {
                        headers: {
                            Authorization: `${AUTH}`,
                        },
                    })
                    .then((response) => {
                        const clippedBranch = {
                            branch: element.name,
                            author: element.target.author.user.display_name,
                            diff: response.data,
                        };
                        console.log(clippedBranch);
                        return clippedBranch;
                    });
            });

        return await Promise.all(requests)
    } catch (error) {
        console.log(error)
        throw error
    }
}

Я не смог проверить это , но концепция все еще применяется

0 голосов
/ 15 апреля 2020

Ваша проблема в .filter l oop. Вы звоните axios.get, но ничего не делаете с обещанием, которое он возвращает. Функция filter должна возвращать true, если объект должен быть сохранен, и false, если нет. Но он вообще ничего не возвращает (что эквивалентно false. Вы можете подумать, что оно возвращает clippedBranch, но это не так.

Я подозреваю, что вы хотите, чтобы filteredByUser был массивом clippedBranch объектов, но в конечном итоге он станет пустым массивом.

Следующий код поможет вам в этом:

let diffs = await axios.get("API-Call-To-BB-For-Recent-Branches", {
  headers: {
    Authorization: `${AUTH}`
  }
});
const filteredByUser = [];
// use forEach instead of filter
diffs.data.values.forEach(async element => {  // <--- use async to allow await
  if (element.target.author.raw.includes(username)) {
    if (element.target.repository.full_name.includes("nameOfMasterBranch")) {
      const clippedBranch = await axios.get(  // <--- wait for the result!
        element.target.links.diff.href, {
          headers: {
            Authorization: `${AUTH}`
          }
        })
        .then(response => {
          let clippedBranch = {
            branch: element.name,
            author: element.target.author.user.display_name,
            diff: response.data
          };
          // Console Logging here shows the data I'm looking for
          console.log(clippedBranch);
          return clippedBranch;
        })
        .catch(error => {
          console.log(error);
        });
      if (clippedBranch) {
        filteredByUser.push(clippedBranch);  // <-- add to array if exists
      }
    }
  }
});

Ваш исходный код ничего не сделал со значением, которое было окончательно разрешено axios.get(href). На самом деле эти вызовы будут завершаться намного позже, чем закончится ваша функция, поскольку вы их вообще не ожидаете.

Я использовал forEach вместо filter, потому что мы хотим обрабатывать каждый вход, но не просто сохранять или отбрасывать его (для этого и нужен filter). Мы хотим построить новый массив, поэтому мы просто push нужных ему вещей, если найдем его, просматривая каждую запись.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...