Помогите с использованием promise в цикле

706
26 ноября 2016, 17:54

У меня есть код

ids = [196658162, 244668541, 84634196, 1234567, 45367181]
for id of ids
  id = ids[id]
  url = "https://api.vk.com/method/users.get?fields=photo,status&user_ids=#{id}&access_token=#{atom.config.get('vk-messenger.apiToken')}&v=5.60"
  reqWithPromise(url)
reqWithPromise = (url) ->
  return new Promise((resolve, reject) ->
    https.get url, (@response) ->
      @response.on 'data', (chunk) ->
        @userModel = JSON.parse(chunk)['response'][0]
        console.log @userModel.id + ' ' + @userModel.first_name
        resolve()
)

в консоле я получаю

1234567 Maximka  dialogs-service.coffee:26
244668541 Maxim  dialogs-service.coffee:26
45367181 Daniil  dialogs-service.coffee:26
84634196 Igor    dialogs-service.coffee:26 
196658162 Nikita dialogs-service.coffee:26

Помогите, как сделать чтобы запросы отправлялись и приходили последовательно.

Answer 1

Для того, чтобы новая операция выполнялась строго после старой - надо начинать делать ее в продолжении старой. Для этого "старое" обещание (promise) нужно сохранять между итерациями цикла:

var last = Promise.resolve();
for (var id of ids) {
    let url = `...`;
    last = last.then(() => reqWithPromise(url));
}

(пишу на javascript, потому что с синтаксисом coffeescript не знаком)

Видно, что переменная last играет роль некоторого аккумулятора, в ней накапливается цепочка вызовов.

Также для построения этой цепочки можно воспользоваться методом reduce:

ids.reduce((last, id) => last.then(() => reqWithPromise(`...`)), Promise.resolve());

Оба способа выше строят длинную цепочку обещаний сразу. Если подобное поведение не устраивает - значит, надо делать цикл через рекурсию:

function reqWithPromiseSeq(ids) {
  step(0);
  function step(index) {
      if (index >= ids.length) return;
      var url = `...`;
      reqWithPromise(url).then(() => step(index+1));
  }
}

Ну и, наконец, можно отказаться от обещаний и использовать вместо них библиотеку async - кажется, функция eachSeries делает именно то, что вам нужно.

READ ALSO
Вывод результата JavaScript

Вывод результата JavaScript

Начал изучение JSСтолкнулся с проблемой, что результат который должен выводить JS не отображается

273
Как извлечь URL страницы в BIRT report

Как извлечь URL страницы в BIRT report

Проблема заключается в отсутствии многих Native JavaScript Functions

261
Ошибка при попытке выполнить grunt build c node v.7.0.0 и npm v.4.0.2

Ошибка при попытке выполнить grunt build c node v.7.0.0 и npm v.4.0.2

При попытке выполнить grunt build вылетает следующая ошибка:

419