Проблема асинхронного ожидания со службой при вызове из контроллера в Nodejs - PullRequest
0 голосов
/ 06 ноября 2019

В настоящее время я пытаюсь выполнить запрос get в моем API NodeJS, получить некоторые данные и вернуть измененное значение.

Из того, что я прочитал в других подобных вопросах, вы не можете просто вернуть измененный объект, но вам нужно использовать функцию callback или обещание для возвратаЭто. У меня есть стандартный шаблон MVC, где я использую controller, service.

Вот мой сервис:

const rp = require('request-promise');
exports.RequestUserPermissions = async function(role, next) {
  try {
    await rp('https://api.myjson.com/bins/7jau8').then(response => {
      const permissionsResponse = JSON.parse(response);
      const filteredPermissions = permissionsResponse.find(function(x) {
        return Object.keys(x).indexOf(role) > -1;
      });
      console.log(filteredPermissions); // I GET UNDEFINED HERE.
      return filteredPermissions;
    });
  } catch (error) {
    console.log(error);
    next(error);
  }
};

Вот мой контроллер:

const UserPermissionsService = require('../services/userPermissions.service');


exports.getUserPermissions = async function(req, res) {
  try {
    const role = req.headers.role; // console.log(req.headers.role);
    const loggedInUserPermissions = await UserPermissionsService.RequestUserPermissions(role);
    return res.status(200).json({ status: 200, data: loggedInUserPermissions, message: 'User permissions retrieved.' });
  } catch (error) {
    throw Error(error, 'error inside the get.user.permissions function');
  }
};

Итак, моя проблема в том, что я пытаюсь вернуть значение filteredPermissions на мой контроллер, но я продолжаю получать неопределенные. По-моему, это проблема async - await. Это означает, что функция заканчивается до того, как я выполню свои вычисления.

Первоначально у меня был сервис:

await request.get('https://api.myjson.com/bins/7jau8', (error, response, body) => {
  if (!error && response.statusCode === 200) {
    const permissionsResponse = JSON.parse(body);
    const filteredPermissions = permissionsResponse.find(function(x) {
      return Object.keys(x).indexOf(role) > -1;
    });
    return permissionsResponse;
  } else {
    console.log('Got an error:', error);
  }
});

, но я изменил его на использование модуля request-promise, чтобы я мог вернутьсямой response. Что я делаю неправильно ? Как правильно пройти мои расчеты ??

Ответы [ 2 ]

1 голос
/ 06 ноября 2019

Если вы используете async / await с request-promise, вам не нужно вызывать .then(), вы можете просто назначить ваш rp вызов непосредственно переменной. Например, это:

await rp('https://api.myjson.com/bins/7jau8').then(response => {
      const permissionsResponse = JSON.parse(response);
      const filteredPermissions = permissionsResponse.find(function(x) {
        return Object.keys(x).indexOf(role) > -1;
      });
      console.log(filteredPermissions); // I GET UNDEFINED HERE.
      return filteredPermissions;
    });

станет следующим:

const response = await rp('https://api.myjson.com/bins/7jau8');
const permissionsResponse = JSON.parse(response);
const filteredPermissions = permissionsResponse.find(function(x) {
  return Object.keys(x).indexOf(role) > -1;
});
console.log(filteredPermissions); // I GET UNDEFINED HERE.
return filteredPermissions;

1 голос
/ 06 ноября 2019

Измените это:

await rp('https://api.myjson.com/bins/7jau8')

на это:

return rp('https://api.myjson.com/bins/7jau8')

Вам необходимо вернуть что-то полезное из функции exports.RequestUserPermissions. В нынешнем виде нет возвращаемого значения из этой функции, что означает, что возвращаемое обещание будет иметь undefined разрешенное значение, которое, по-видимому, является тем, что вы испытываете.

Затем я бы предложил использовать .catch() для условия ошибки. И вам нужно разрешить вызывающей стороне видеть ошибку (вероятно, как отклоненное обещание), чтобы он мог знать, когда есть ошибка.

Я бы предложил это:

const rp = require('request-promise');
exports.RequestUserPermissions = function(role, next) {
    return rp('https://api.myjson.com/bins/7jau8').then(response => {
      const permissionsResponse = JSON.parse(response);
      const filteredPermissions = permissionsResponse.find(function(x) {
        return Object.keys(x).indexOf(role) > -1;
      });
      console.log(filteredPermissions); // I GET UNDEFINED HERE.
      return filteredPermissions;
    }).catch(error => {
      console.log(error);
      next(error);
      throw error;
    });
};

Спецификация именно того, что вы хотите, немного запутана. Чтобы иметь возможность проверять вещи с помощью URL, который вы мне дали, я создал здесь простую автономную программу для узлов. Это ищет один соответствующий role и возвращает это. Если подходящая роль не найдена, она разрешается до null. Вы также можете сделать это отклонение, в зависимости от того, как вызывающий не хочет, чтобы подходящая роль работала.

const rp = require('request-promise');

function getRole(role) {
    return rp({uri: "https://api.myjson.com/bins/7jau8", json: true}).then(data => {
        // need to find the matching role
        // apparently role can be a string or an array of strings
        for (let item of data) {
            if (item[role]) {
                return item[role];
            }
        }
        return null;
    });    
}

getRole("admin").then(data => {
    console.log(data);
}).catch(err => {
    console.log(err);
});

Когда я запускаю это, я получаю такой вывод:

{ static:
   [ 'posts:list',
     'posts:create',
     'posts:edit',
     'posts:delete',
     'users:get',
     'users:getSelf',
     'home-page:visit',
     'dashboard-page:visit' ] 
}

Надеюсь,Можете ли вы использовать эту модификацию в соответствии с вашими другими потребностями.

Примечание: я использую опцию json:true с rp(), поэтому она автоматически проанализирует ответ JSON для меня.

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