Использование обещания. Все, чтобы сделать внешние вызовы API в node js - PullRequest
1 голос
/ 23 февраля 2020

Я использую пакет request-обещание npm, чтобы сделать несколько вызовов API в nodeJS. Чтобы получить необходимые мне данные, мне нужно было бы циклически проходить по всем категориям, а затем в каждой категории проходить по массиву продуктов, чтобы получить информацию о продукте. Пример ответа по категориям приведен ниже мне ошибка 404 не найдена, может кто-нибудь, пожалуйста, помогите мне, где я иду не так здесь? ниже я попробовал

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

const requestUrl = "https://stage.tuscanyleather.it/api/v1/";
const categoryRequestUrl = requestUrl + 'categories';
let tuscanApiOptions = {
    uri: categoryRequestUrl,
    headers: {
        'Authorization': 'Bearer asd343'
    },
    method: 'Get',
    json: true 
};

rp(tuscanApiOptions)
    .then((categResponse) => {
        //res.end(categResponse);  
        let ps = [];
        categResponse.response.forEach((category) => {
            if (category.products !== undefined) {
                category.products.forEach((product) =>{
                    let productApiOptions = {
                        uri: requestUrl + `product-info?code=${product}`,
                        headers: {
                            'Authorization': 'Bearer asd343'
                        },
                        method: 'Get',
                        json: true 
                    };
                    ps.push(rp(productApiOptions));
                });
                Promise.all(ps)
                    .then((values) => {
                        console.log(values); //This is where things are going wrong
                  })
                    .catch((err) =>{
                        console.log(JSON.stringify(err,null,2));
                    })
            }

        })

    })
    .catch((error) => {
        console.log(error);
        //res.status(error.statusCode).send(error.error.error_description);
    });

1 Ответ

2 голосов
/ 24 февраля 2020

Этот код должен помочь вам отладить 404:

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

const requestUrl = "https://stage.tuscanyleather.it/api/v1/";
const categoryRequestUrl = `${requestUrl}categories`;
const tuscanApiOptions = {
  uri: categoryRequestUrl,
  headers: {
    'Authorization': 'Bearer asd343'
  },
  method: 'Get',
  json: true 
};

// Promise of flat array of products (loses category data)
const productsP = rp(tuscanApiOptions))
  .then(({response}) => response
    .map(category => category.products) // array of arrays
      .flat() // flatten to array of products
      .filter(p => !!p) // remove empty 
  )

const prodUrl = `${requestUrl}product-info?code=`

const productDataP = productsP.then(products => 
  products.map(product => 
    rp({
      ...tuscanApiOptions,
      uri: `${prodUrl}${product}` 
    }).catch(e => `Error fetching ${prodUrl}${product} ${e.message}`)
  )
)

// Wait for all requests to resolve with data or error. 
// resultsP is an array of Promise<productdata|error>
const resultsP = Promise.all(productsDataP)

resultsP.then(console.log)             

Несколько предложений, возьмите их или оставьте их:

Выньте Array.forEach из своего словаря программирования , Это вызовет у вас больше проблем, чем решит, потому что это побочный эффект (по сути, все oop). Используйте Array.map, чтобы вернуть новый массив, затем оперируйте этим. Array.map отделяет конечный автомат от преобразования данных, forEach смешивает их вместе.

Не используйте let или var для вещей, которые не мутируют. Это говорит другим программистам и машине не полагаться на ценность. Используйте const.

Более подробное объяснение см. в этой статье .

Может быть проще сделать это с async / await, по крайней мере, для отладки. У вас есть обход структуры данных и асин c монад (Обещание), с которыми вы здесь сталкиваетесь, и 404, которые вам нужно отладить. await Обещание расширяет значение из контекста монады, поэтому оно устраняет один уровень сложности.

Когда у вас есть массив Обещаний, вы await Promise.all(arrayP) получаете массив развернутых значений.

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

const requestUrl = "https://stage.tuscanyleather.it/api/v1/";
const categoryRequestUrl = `${requestUrl}categories`;
const tuscanApiOptions = {
  uri: categoryRequestUrl,
  headers: {
    'Authorization': 'Bearer asd343'
  },
  method: 'Get',
  json: true 
};

async function main() {
  const categories = await rp(tuscanApiOptions)
  const products = categories.response
    .map(category => category.products) 
    .flat() 
    .filter(p => !!p) // remove undefined

  console.log(products) // should be flat array of products

  const prodUrl = `${requestUrl}product-info?code=`

  const requestsP = products
    .map(product => 
      rp({
        ...tuscanApiOptions,
        uri: `${prodUrl}${product}` 
      }).catch(e => `Error fetching ${prodUrl}${product} ${e.message}`)
  )

  const results = await Promise.all(requestsP)

  console.log(results)
}

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