Как отправить несколько запросов Ax ios одновременно? - PullRequest
4 голосов
/ 23 апреля 2020

На данный момент у меня есть веб-страница, на которой выполняется длинный список вызовов Ax ios POST. Теперь кажется, что запросы отправляются параллельно (JavaScript продолжает отправку следующего запроса до получения результата).

Однако результаты, похоже, возвращаются один за другим, а не одновременно. Допустим, один POST-вызов скрипта PHP занимает 4 секунды, и мне нужно сделать 10 вызовов. В настоящее время это займет 4 секунды на звонок, что в общей сложности составит 40 секунд. Я надеюсь найти решение для обоих и получить все результаты примерно в одно и то же время (~ 4 секунды) вместо ~ 40 секунд.

Теперь я читал о потоках, многопоточность которых NodeJS с использованием Workers. Я читал, что JavaScript сам по себе является однопоточным, поэтому он сам по себе не может этого допустить.

Но я не уверен, откуда отсюда go. У меня есть только идеи. Я не уверен, направляюсь ли я в правильном направлении и, если да, я не уверен, как использовать Workers в NodeJS и применить это в моем коде. По какой дороге мне идти? Любое руководство будет высоко ценится!

Вот небольшой пример кода:

for( var i = 0;  i < 10;  i++ )
{
    window.axios.post(`/my-url`, {
        myVar: 'myValue'
    })
    .then((response) => {
        // Takes 4 seconds, 4 more seconds, 4 more seconds, etc
        // Ideally: Takes 4 seconds, returns in the same ~4 seconds, returns in the same ~4 seconds, etc
        console.log( 'Succeeded!' );
    })
    .catch((error) => {
        console.log( 'Error' );
    });

    // Takes < 1 second, < 1 more second, < 1 more second, etc
    console.log( 'Request sent!' );
}

Ответы [ 6 ]

7 голосов
/ 04 мая 2020

Вы можете достичь цели тремя способами.

1) Для одновременных запросов с Ax ios вы можете использовать Axios.all()

axios.all([
  axios..post(`/my-url`, {
    myVar: 'myValue'
  }), 
  axios.post(`/my-url2`, {
    myVar: 'myValue'
  })
])
.then(axios.spread((data1, data2) => {
  // output of req.
  console.log('data1', data1, 'data2', data2)
}));

2) используйте Promise.allSettled(). Метод Promise.allSettled () возвращает обещание, которое разрешается после того, как все обещания были либо разрешены, либо отклонены,

3) Вы можете попытаться использовать Promise.all(), но у него есть недостаток, заключающийся в том, что если 1 req завершилась неудачно, тогда она не удастся для всех и выдаст o / p как ошибку (или в блоке catch)

, но лучший вариант - первый.

1 голос
/ 01 мая 2020

Для одновременных запросов с Ax ios вы можете использовать Ax ios .all ().

axios.all([
  axios.get('https://api.github.com/users/MaksymRudnyi'), 
  axios.get('https://api.github.com/users/taylorotwell')
])
.then(axios.spread((obj1, obj2) => {
  // Both requests are now complete
  console.log(obj1.data.login + ' has ' + obj1.data.public_repos + ' public repos on GitHub');
  console.log(obj2.data.login + ' has ' + obj2.data.public_repos + ' public repos on GitHub');
}));

Также вы можете использовать Promise.all (). Работает аналогично:

Promise.all([
  fetch('https://api.github.com/users/MaksymRudnyi'),
  fetch('https://api.github.com/users/taylorotwell')
])
.then(async([res1, res2]) => {
  const a = await res1.json();
  const b = await res2.json();
  console.log(a.login + ' has ' + a.public_repos + ' public repos on GitHub');
  console.log(b.login + ' has ' + b.public_repos + ' public repos on GitHub');
})
.catch(error => {
  console.log(error);
});

Но в Promise.all () есть специфическое c поведение. В случае отклонения хотя бы одного запроса - весь запрос будет отклонен, а код будет go к разделам .catch (). Это нормально, если вам нужно убедиться, что все запросы разрешены.

В случае, если все в порядке, когда некоторые ваши запросы отклонены, рассмотрите возможность использования Promise.allSettled (). Метод Promise.allSettled () возвращает обещание, которое разрешается после разрешения или отклонения всех данных обещаний, с массивом объектов, каждый из которых описывает результат каждого обещания.

1 голос
/ 23 апреля 2020

Попробуйте таким образом

window.axios.all([requestOne, requestTwo, requestThree])
  .then(axios.spread((...responses) => {
    const responseOne = responses[0]
    const responseTwo = responses[1]
    const responesThree = responses[2]
    // use/access the results 
  })).catch(errors => {
    // react on errors.
  })
0 голосов
/ 02 мая 2020

Это странно и не должно происходить. Механизмы Javascript являются однопоточными, а веб-API (которые используются внутри при выполнении запросов AJAX) - нет. Таким образом, запросы должны быть сделаны примерно в одно и то же время, а время ответа должно зависеть от времени обработки сервера и задержек в сети.

Веб-браузеры имеют ограничение на количество соединений на сервер (6 в chrome https://bugs.chromium.org/p/chromium/issues/detail?id=12066), что объясняет некоторую сериализацию. Но не это.

Поскольку запросы занимают 4 секунды, что составляет long , я предполагаю, что проблема в сервере. Он может обрабатывать только 1 соединение за раз. Вы контролируете это?

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

Попробуйте это с Ax ios .all и

  • Использование метода Promise.all () возвращает одно Обещание, которое выполняется, когда все обещания, переданные как итеративные, выполнены. Обещание MDN ref Link

    import axios from 'axios';
    let one = "https://api1"
    let two = "https://api2"
    let three = "https://api3"
    
    const requestOne = axios.get(one);
    const requestTwo = axios.get(two);
    const requestThree = axios.get(three);
    
    axios.all([requestOne, requestTwo, requestThree]).then(axios.spread((...responses) => {
      const responseOne = responses[0]
      const responseTwo = responses[1]
      const responesThree = responses[2]
      // use/access the results 
    console.log("responseOne",responseOne);
    console.log("responseTwo",responseTwo);
    console.log("responesThree",responesThree);
    })).catch(errors => {
      console.log(errors);
    })
    

Ref Link

Найти полный пример здесь для топора ios

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

Если вы хотите иметь его в пределах oop, вы можете иметь слегка измененную версию @deelink, как показано ниже

let promises = [];
for (i = 0; i < 10; i++) {
  promises.push(
    window.axios.post(`/my-url`, {
    myVar: 'myValue'})
   .then(response => {
      // do something with response
    })
  )
}

Promise.all(promises).then(() => console.log('all done'));
...