javascript ładowanie z dwóch plików

0

Cześć,
Chciałem dowiedzieć się na temat jednego z rozwiązań.
Posiadam dwa pliki z klasami w php które zwracają mi wartości w JSON.
Chciałem zrobić ładowanie tych wartości za pomocą javascript. Problem polega na tym, że aby pobrać wartości z drugiego pliku PHP muszę przesłać parametr, który pobieram w pierwszym.
Czyli mam coś takiego:

var devices = $.post("PHP/espDevices.php",{menu: 0}); - to pobiera mi nazwy urządzeń oraz ich ID.
Teraz chciałbym, aby z drugiego pliku pobrać historię dla tych urządzeń wysyłając parametr ID pobrany z poprzedniego, czyli coś takiego.
$.post("PHP/espHistory.php",{menu : 0, deviceId : i tutaj id z poprzedniego }))

W jaki sposób można to zrealizować w JS.
Próbowałem zrobić to w taki sposób:

var devices = $.post("PHP/Devices.php",{menu: 0});
    $.when(devices)
            .then(function(dataDevices){
                dataDevices = JSON.parse(dataDevices);
                $.each(dataDevices,function(key,val){
                    $.when($.post("PHP/History.php",{menu : 0, deviceId : val.id }))
                            .then(function(history){
                                history =JSON.parse(history);
                                console.log(history);
                    })
                    
                })

Teoretycznie to działa, ale problem jest w tym, że dane są wyświetlane losowo w kolejności załadowania, a nie w kolejności w jakiej występują przy pobraniu z Device.php dlatego, że robię to za pomocą promise.
Czy mogę prosić o pomoc w jaki sposób najlepiej załadować dane z dwóch różnych plików (które zawracają JSON) gdzie do drugiego trzeba przekazać parametr z pierwszego i połączyć je jakoś w jedne zwracane wartości w kolejności występowania ich w zawartości json device.php ?

0

do $.when możesz podawać serię deferred-ów, czyli

var d1 = $.post();
var d2 = $.post();
 
$.when( d1, d2 ).done(function ( v1, v2 ) {
    console.log( v1 ); // wynik pierwszego
    console.log( v2 ); // wynik drugiego
});

ponieważ ty nie znasz ilości urządzeń z tego miejsca w kodzie to zapakujesz to w arraya:

var defs = [];
defs.push($.post());
defs.push($.post());
defs.push($.post()); // itd.

następnie użyjesz apply by podać wartości tablicy jako argumenty ($.when nie przyjmie "normalnie" tablicy)

var queue = $.when.apply($, defs);

z kolei w done dostaniesz wyniki w kolejnych argumentach (jak w pierszym przykładnie)

queue.then(function(v1, v2, .... /* nie znamy ilości przekazanych parametrów */) {
  // na szczęście mamy trochę magiczną zmienną `arguments`
  $.each(arguments, function(key, val) {
     // tu robisz z wynikiem w `val` co potrzebujesz
  });
});

Pisane z palca, więc mogą być literówki.

0

Przepraszam, ale nie do końca jeszcze rozumiem.
Robię coś takiego:

var defs = [];
defs.push($.post("PHP/Devices.php",{menu: 0}));

w tym momencie pobieram listę urządzeń z device w formacie JSON, czyli coś takiego:
[{"id":"1","deviceName":"Urządzenie 1"},{"id":"2","deviceName":"Urządzenie 2"}]
Teraz nie wiem w jaki sposób mam pobrać "id" z tego jsona do pobrania danych z kolejnego pliku. Dodam, że w klasie w PHP(history.php) mam metodę która pobiera dane po ID urządzenia.

Próbowałem zrobić coś takiego:

var def=[];
       def.push($.post("PHP/Service.php",{menu: 0},"JSON"));
       var que = $.when.apply($,def);
              que.then(function(){
                  var historyDef = [];
                  $.each(arguments, function(key,val) {
                     historyDef.push($.post("PHP/History.php",{menu : 0, deviceId : ? }))
                  console.log(val);     
                   });
                  
              }) 

ale nie wiem w jaki sposób te deviceId pobrać..

0

Ale to po kolei, bo teraz dokleiłeś jakieś Service.php, a wcześniej tego nie było.

Daj przykład co każdy z tych plików przyjmuje i co zwraca.

0

a to dziwne.. nie wiem skąd się tutaj w kodzie wzięło to service.php ;/ tym bardziej, że u siebie kodzie nigdzie tego nie mam... ale mniejsza o to.

A więc tak:
Plik devices.php przyjmuje tylko menu = 0 i zwraca mi listę urządzeń w formacie JSON:
[{"id":"1","deviceName":"Urządzenie 1"},{"id":"2","deviceName":"Urządzenie 2"}]

teraz dla tych urządzeń chcę pobrać dane z pliku history.php, który przyjmuje dwa parametry - menu = 0 oraz id urządzenia (wcześniej pobrane z device.php) i zwraca mi JSON z danymi. Kolejno z tych dwóch danych chcę wyświetlić informacje w tabeli.

0

Czy ktoś jest w stanie pomóc z tym problemem ?

1

Sorki, że tak późno ;) Mogłeś zawołać jeszcze raz.

Okazuje się, że natywne Promises są tyle lepsze niż Defferredy, że Promise.all przyjmuje arraya jako argument, więc nie trzeba się bawić z apply i wynik też jest w arrayu i nie ma zabawy z arguments na wyniku ;) Sam dopiero od niedawna się tym bawię, więc nawet nie skojarzyłem.

W załączniku pełen przykład, wraz z symulacją zwrotu w innej kolejności (im mniejsze id, tym dłużej czeka, by "późniejsze" id zwrócić od razu, a na pierwszym urządzeniu czekać).

Kod js wklejam też poniżej:

$(document).ready(function(){

    var load_devices = function() {
        return Promise.resolve($.post("PHP/Devices.php", { menu:0 }))
            .then(JSON.parse);
    };

    var load_history = function(data) {
        var defs = [];
        data.forEach(function(val) {
            defs.push(
                Promise.resolve($.post("PHP/History.php?"+val.id, { menu: 0, deviceId: val.id }))
                    .then(JSON.parse)
            );
        });

        return Promise.all(defs);
    };

    var display_history = function(values) {
        console.log(values);
    };


    load_devices()
        .then(load_history)
        .then(display_history);
});

Defferredy od razu konwertowałem na natywne Promises, korzystam z jQuerowego ajaxu tak jak Ty, żeby przynajmniej tyle nie mieszać. Nie korzystam z podawania trzeciego parametru jako JSON, bo u mnie i tak zwracało stringa, nie wiem dlaczego (być może TRZEBA podać callback jednak?), stąd dodałem JSON.parse.

ID w GET dodałem po to, żeby na screenshocie było widać, że ID 1 ładował się najdłużej, ale w wynikach i tak jest pierwszy :)

user image

Do kodu pasuje dopisać jakiś catch na błędy.

0

dzięki kolego.
mam jeszcze jedno tylko pytanie. A jak wyświetlić dane z pierwszego promisa (devices) ?
ponieważ w przypadku dodania funkcji

var dispaly_devices = function(data){
console.log(data)
}

oraz dodanie tego do :

 load_devices()
         .then(dispaly_devices)
        .then(load_history)
        .then(display_history);

nie działa wykonanie metody load_history ponieważ nie można znaleźć obiektu data

1

niech display_devices zwróci to, co dostał, tj. na końcu dopisz return data - kolejne then dostają w parametrze dane zwrócone przez poprzedni then

0

Dzięki kolego !
Wszystko działa tak jak powinno :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1