Отправка нескольких запросов API с помощью Promise - PullRequest
2 голосов
/ 01 апреля 2019

Как отправить несколько запросов API? поэтому у меня есть этот код ниже

 const productID= [12, 43, 65, 87, 45, 76, 87];
    productID.map(id => {
     API.removeItem(id, (err, response) => {
       if (response.status === 'success') {
           console.log('remove a product');
        }else {
          console.log(err); 
        }
     })
})

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

async function removeProducts() {
    const productID = [12, 43, 65, 87, 45, 76, 87];
    const result = await Promise.all(productID.map(id => {
        API.removeItem(id, (err, response) => {
            if (response.status === 'success') {
                console.log('remove a product');
            }else {
                console.log(err); 
        }
        });
    }));
}

Результат почти такой же, как в первом фрагменте кода, но на этот раз удалось удалить 2 элемента продукта. Я хочу, чтобы следующий запрос был сделан, только если предыдущий запрос завершен. Как я могу это сделать?

Ответы [ 4 ]

1 голос
/ 01 апреля 2019

Проблема с вашей второй попыткой состоит в том, что Promise.all() принимает массив обещаний в качестве аргумента. Функция Promise.all() также возвращает само обещание, которое разрешается, когда каждое обещание в переданном массиве разрешается.

array.map не возвращает обещание, оно возвращает новый массив с результатами каждого элемента в массиве, вызванном с помощью предоставленной функции. Подробнее о функции карты здесь .

Вместо этого создайте функцию-оболочку для вызова API, которая возвращает обещание.


const productID = [12, 43, 65, 87, 45, 76, 87];

let removeProductID = (id) => {
    return new Promise((resolve, reject) => {
        API.removeItem(id, (err, response) => {
            if (response.status === 'success') {
                console.log('remove a product');
                resolve(response);
            } else {
                console.log(err);
                reject(err);
            }
        })
    });
}

let removeAllProductIDs = async () => {
    for(let id of productID) {
        await removeProductID(id);
    }
}

removeAllProductIDs();

0 голосов
/ 02 апреля 2019

Как и другие ответы, начните с обещания API.removeItem (Если ваша среда Node.js, вы можете использовать util.promisify, в противном случае используйте конструктор Promise, как показано в других ответах):

const {promisify} = require('util');

const removeItem = promisify(API.removeItem);

Тогда, если вы не возражаете против добавления стороннего модуля, вы можете использовать async-af (модуль, который я поддерживаю) для последовательного просмотра идентификаторов с использованием async forEach * * 1014

const AsyncAF = require('async-af');

const removeItems = ids => AsyncAF(ids).series.forEach(removeItem);

removeItems([12, 43, 65, 87, 45, 76, 87]);

Кроме того, вы можете использовать vanilla JS для последовательного просмотра идентификаторов; например, вот реализация, использующая Array.prototype.reduce:

const removeItems = ids => ids.reduce((acc, id) => (
  acc.then(() => removeItem(id))
), Promise.resolve());

removeItems([12, 43, 65, 87, 45, 76, 87]);
0 голосов
/ 01 апреля 2019
const productID = [12, 43, 65, 87, 45, 76, 87];
function process() {
    if (productID.length == 0) return;

    var id = productID.pop();
    API.removeItem(id, (err, response) => {
       if (response.status === 'success') {
           console.log('remove a product');
           process(); // process next item if success
        } else {
          console.log(err); 
        }
    });
};

process();
0 голосов
/ 01 апреля 2019

На самом деле Promise.All () сделать параллельный запрос, так что это не решение, которое вы ищете.

Вам нужно, чтобы дал результат, затем сделал еще один запрос и так далее. Для этого вам нужно API.removeItem для возврата Promise . Если это не так, вы можете обернуть эту функцию с помощью API Promise для возврата Promise.

    async function removeItem(id) {
      return new Promise((resolve, reject) => {
        API.removeItem(id, (err, response) => {
          if (response.status === 'success') {
            resolve("message or data"); // or pass id or anything
          } else {
            console.log(err);
            reject(err)
          }
        })
      })
    }

Теперь вы можете использовать эту функцию для получения результата.

 const productID = [12, 43, 65, 87, 45, 76, 87];
    async function removeProducts() {
       for (let i = 0; i < productID.length; i++) {
            const result = await removeItem(productID[i]); // will return resolved value here
            // sequence
          }
     }
...