Callback в цикле

Тема в разделе "JavaScript", создана пользователем dirdir, 3 янв 2018.

  1. dirdir

    dirdir Постоялец

    Регистр.:
    19 мар 2012
    Сообщения:
    107
    Симпатии:
    12
    Такая ситуация вот.

    HTML:
    
    // Это просто массив объектов. Не в нем суть
    var cripta = [
        {
            name : 'ltc',
            zakup : 800
        },
        {
            name : 'btc',
            zakup : 90000
        }
    ];
    
    // Для интереса пихнули в локалсторэйдж
    cripta = JSON.stringify (cripta);
    localStorage['cripta'] = cripta;
    
    
    // Здесь  при клике на кнопку запрашиваем данные с сайта. В функции обратного вызова 
    // criptanamenow   ВСЕГДА имеет значении взятое из последней интерации в массиве
    $$('#myload').on('click', function (e) {
    
        // Get page data from event data
        var cripta = JSON.parse(localStorage['cripta']);
        for (var i=0, len=cripta.length; i<len; i++)
        {
          criptanamenow =  cripta[i].name+'_rur';
           alert (criptanamenow);
        var urlnow = 'https://yobit.net/api/3/ticker/'+criptanamenow;
        $$.get(urlnow, {id: 3}, function (data) {
               
                        var datanow;
                        data= JSON.parse(data);
                       //-----------  ВОТ ТУТ ЗНАЧЕНИЕ ВСЕГДА ПОСЛЕДНЕЕ ИЗ МАССИВА.
                        alert (criptanamenow);
                        datanow = '<p>'+data[criptanamenow].high+'</p>';
                        $$('#insertdata').append( datanow);
                        console.log(data);
                       
                      });
    
        }
    
    });
    Почему так происходит что цикл перебирается, делается запрос к сайту.
    НО в функции обртного вызова всё время последнее значение из массива?
    criptanamenow - туда попадает только из последней интерации.
     
  2. Sorcus

    Sorcus Sorcus. A New Beginning.

    Moderator
    Регистр.:
    10 июл 2011
    Сообщения:
    424
    Симпатии:
    783
    У тебя проблемы с основами js-а.
    - изучай.
    Быстрофикс:
    HTML:
    let criptanamenow =  cripta[i].name+'_rur';
    1. Не используй var там, где это не нужно. Есть let и const.
    2. Не создавай переменных путем присваивания без let / const (criptanamenow как пример).
    3. Точки с запятой не обязательны. Есть лишь пара-тройка ситуаций, когда они нужны.
    4. Пиши на ES2015.
    5. Это:
    HTML:
    '<p>'+data[criptanamenow].high+'</p>'
    можно записать как:
    HTML:
    `<p>${data[criptanamenow].high}</p>`
     
    dirdir, Nei, Q_BASIC и ещё 1-му нравится это.
  3. dirdir

    dirdir Постоялец

    Регистр.:
    19 мар 2012
    Сообщения:
    107
    Симпатии:
    12
    да, проблемы есть. Допустим я могу анонимную функцию, которая замыкает вызывать сразу, т.к. это function expression.
    Добавлю скобушки с передачей аргумента

    вот так
    HTML:
    $$.get(urlnow, {id: 3}, function (data) {
               
                        var datanow;
                        data= JSON.parse(data);
                       //-----------  ВОТ ТУТ ЗНАЧЕНИЕ ВСЕГДА ПОСЛЕДНЕЕ ИЗ МАССИВА.
                        alert (criptanamenow);
                        datanow = '<p>'+data[criptanamenow].high+'</p>';
                        $$('#insertdata').append( datanow);
                        console.log(data);
                       
                      }(criptanamenow));
    Тогда конечно в функцию передастся нужный параметр из цикла.

    Только как теперь получить data , который содержит Response ? его-то в таком случае не будет в функции
     
  4. dirdir

    dirdir Постоялец

    Регистр.:
    19 мар 2012
    Сообщения:
    107
    Симпатии:
    12
    $$.get Пихает свою
    data с responseText и никак не пойму как ещё передат туда аргументов
     
  5. MaxiSoft

    MaxiSoft

    Moderator
    Регистр.:
    5 апр 2007
    Сообщения:
    206
    Симпатии:
    146
    тут скорее нужно начинать не с колбеков, и запросов в цикле, :) я сделать по нормальному как правильные пацаны, покурить для начала api и понять что можно все сделать вот таким запросом
    https://yobit.net/api/3/ticker/btc_rur-ltc_rur

    ну а после уже без изврата разобрать json response

    P>S. а за запросы в цикле вообще нужно на костер или на кол садить.
     
    Sorcus нравится это.
  6. Sorcus

    Sorcus Sorcus. A New Beginning.

    Moderator
    Регистр.:
    10 июл 2011
    Сообщения:
    424
    Симпатии:
    783
    Хз что ты пытаешься получить в итоге, но если нужно передавать аргументы, тогда выноси запрос в отдельную функцию.
    HTML:
    const api_func = (arg1, arg2, ...array_of_args) => {
      // Здесь твоя функция для получения данных по url.
    }
    И соответственно этот api_func() дергаешь в нужных местах.
     
  7. Absolute

    Absolute Крокодил ;)

    Регистр.:
    9 авг 2009
    Сообщения:
    481
    Симпатии:
    322
    Так происходит, потому что по-умолчанию запросы выполняются асинхронно и цикл не ждет пока отправится запрос и придет результат - цикл просто моментально выполняется. Можно отключить асинхронные запросы (async: false), но это не путь джедая, а тем более в цикле.
    Но если других путей нет, можно поступить примерно так, отправив поочереди значения массива асинхронно.
    HTML:
    var a = [23, 84, 99]; // какой-то массив, значения кот.отправляем
      function sendArray(){ // эту функцию будем вызывать при успешном получении ответа пока массив не пуст
          $.ajax({
            url: url,
            data: a.shift(), // всякий раз удаляем первое значение из массива и возвращаем его сюда, пока массив не закончится
            success: function(data){
             if(a.length !== 0){ // все ли элементы массива отправили, остались значения - ок...
                sendArray(); // вызываем функцию
             }
            }
          });
      }
     
    Последнее редактирование: 5 янв 2018
    Sorcus нравится это.