отправка ответов API на глобальную переменную внутри .map () делает данные недоступными - PullRequest
0 голосов
/ 08 мая 2018

Я создал функцию, которая выполняет серию вызовов API через Promise, как это

//userApiList is a variable with an array of links
return Promise.all(userApiList.map(url =>{
    var a = $.getJSON(url);
    //userData is a global variable
    userData.push(a);
    return a;
}));

Я хочу сохранить данные в переменную для последующего использования и сразу же вернуть их для повторения в html с помощью jquery. Все загружается идеально, как и ожидалось, однако, когда я обращаюсь к данным в переменной, я получаю все «неопределенные» свойства. Я console.logged переменная, и она показывает, что данные есть, я нажимаю кнопки хорошо после того, как данные извлекаются, поэтому это не асинхронная проблема. вот пример одной из функций

$("#load_online").click(function(){
    var users = [];

    for(var i = 0; i < userData.length; i++){
      var status = userData[i].status;
      if(status !== null || status !== undefined){ users.push(userData[i]); }
    }
    $("#result_frame").empty();
    //loadUsers() iterates the data into html
    loadUsers(users);
});

Я попытался console.log(userData[i].status) просто посмотреть, каковы будут результаты, и я получил 200 в качестве ответа, когда предполагается, что это null' или название эпизода, передаваемого на канал.

Проблема в том, что я думал, что поле responseJSON: - это то, что всегда возвращается для использования, поскольку я никогда раньше не рассматривал эту проблему. На этот раз кажется, что весь объект читается, поэтому userData[i].status считывал свойство status: на уровень выше, а не внутри объекта responseJSON:. Я попытался подумать, получив ответ из userData[i].responseJSON.status, и он дал неопределенное значение для каждого объекта. Кто-нибудь с готовностью видит, что я делаю не так? Вот CodePen всего проекта, если вам нужно более внимательно посмотреть на вещи.

Ответы [ 2 ]

0 голосов
/ 08 мая 2018

согласен с верхним ответом,

это тоже может сработать,

return userApiList.map(url => { $.getJSON(url).done(function(results){ userData.push(results) });})

0 голосов
/ 08 мая 2018

Вы не помещаете данные в свой массив, вы вставляете в него объект jQuery jqXHR (который thenable , например, Promise-like) (вот что возвращаемое значение $.getJSON). Причина того, что результат Promise.all работает, заключается в том, что Promise.all ожидает разрешения этих элементов.

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

Но если вы действительно хотите заполнить userData, дождитесь разрешения:

return Promise.all(userApiList.map($.getJSON))
    .then(results => {
        userData.push(...results);
        return results;
    });

Обратите внимание, что userData не будет иметь данных, пока запросы ajax не будут выполнены (конечно).

Вышеуказанное не добавит результаты к userData, пока они не будут all avaialble. У вас также есть возможность заполнить его по ходу:

return Promise.all(userApiList.map(url => $.getJSON(url).then(result => {
        userData.push(result);
        return result;
    })));

Но важно помнить, что результаты будут добавляться со временем, а не мгновенно, по мере выполнения запросов.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...