Выполнять последовательные запросы, обрабатывая каждый - PullRequest
0 голосов
/ 31 января 2019

Мне нужно отправлять запросы в последовательности, но останавливать последовательность, когда возвращается ошибка, я использую $ http провайдера от angular.

Мой код такой:

const steps = [
    { url: '/api/test/1' },
    { url: '/api/test/2' },
    { url: '/api/test/3' },
    { url: '/api/test/4' },
]

const executeStep = index => {
    // Validate step existence
    if (typeof steps[index] == 'undefined') return
    // Request
    $http({method: 'get', url: steps[index].url})
    .success(response => {
        if (!response.success) throw response
        executeStep(index+1)
    }).error(err => {
        console.error(err)
        alert('Error')
    })
}

executeStep(0)

Мой вопрос: Есть ли лучший способ сделать эту работу?

Ответы [ 3 ]

0 голосов
/ 31 января 2019

То, что вам нужно, это цепочка обещаний и рекурсия.

const steps = [
    { url: '/api/test/1' },
    { url: '/api/test/2' },
    { url: '/api/test/3' },
    { url: '/api/test/4' },
]

const executeStep = index => {
    // Validate step existence
    if (typeof steps[index] == 'undefined') return true;
    // Request
    return $http({method: 'get', url: steps[index].url})
    .then(response => {
        if (!response.success) throw response
        return executeStep(index+1)
    })
}

executeStep(0)
  .then( () => console.log('all done'))
  .catch(e => console.error('something failed', e))

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

0 голосов
/ 31 января 2019

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

const queue = [
  { url: '/api/test/1' },
  { url: '/api/test/2' },
  { url: '/api/test/3' },
  { url: '/api/test/4' },
];

function oneRequest(req) {
    return new Promise((resolve,reject)=>{
        $http({method: 'get', url: req.url})
            .success(response => resolve(response))
            .error(err => reject(err));
    });
}

async function allRequests(reqs) {
    let resps = [];
    for(var i=0;i<reqs.length;i++) {
        let resp = await oneRequest(reqs[i]);
        resps.push(resp);
    }
    return resps;
}

allRequests(queue)
    .then(resps => console.log(resps))
    .catch(err => console.log(err));
0 голосов
/ 31 января 2019

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

const queue = [
  { url: '/api/test/1' },
  { url: '/api/test/2' },
  { url: '/api/test/3' },
  { url: '/api/test/4' },
];

function runQueue() {
  const req = queue[0];

  $http({method: 'get', url: req.url})
  .success(response => {
    console.log(response);
    queue.shift();
    if (queue.length > 0) {
     runQueue();
    }
  })
  .error(err => {
    console.error(err);
  })
}

Решение с использованием Bluebird Promises.

Другим хорошим вариантом может быть (особенно если ваш код является nodejs на стороне сервера) использование библиотеки bluebird Promise .Эта библиотека в настоящее время не очень популярна, потому что Promises поддерживаются практически везде.Но все же некоторые методы очень полезны.В вашем случае Promise.each метод будет отлично работать.

const Promise = require('bluebird'); // or import * as Promise from 'bluebird';
const queue = [
      { url: '/api/test/1' },
      { url: '/api/test/2' },
      { url: '/api/test/3' },
      { url: '/api/test/4' },
    ];

Promise.each(queue, (req) => {
    return http$({method: 'get', url: req.url}).then((resp) => {
            console.log(resp);
        });
}).then(() => {
    console.log("done");
}).catch(err => {
   console.error(err);
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...