2016-04-24 9 views
5

Sto provando a utilizzare il valore della prima chiamata ajax nella seconda chiamata ajax. Sto usando la struttura del codice qui sotto. Per qualche motivo la seconda chiamata restituisce undefined per il userLocationvariable. Come posso refactoring il mio codice in modo che il valore userLocation dalla prima chiamata ajax possa essere utilizzato nell'url della seconda chiamata ajax?Utilizzare jquery.quando è necessario per passare un valore da una chiamata ajax a un'altra

var userLocation; 

function getUserLocation() { 
    $.ajax({ 
    url: 'https://www.example.com/location.json', 
    success: function(response) { 
     userLocation = response.coordinates; 
    } 
    }); 
} 

function getCurrentWeather() { 
    $.ajax({ 
    url: 'https://www.example.com/weather' + userLocation + '.json', 
    success: function(response) { 
     console.log(response); 
    } 
    }); 
} 


$(document).ready(function() { 
    $.when(
    getUserLocation() 
).done(
    getCurrentWeather() 
) 
}); 

UPDATE 1: Grazie alle risposte fornite di seguito sono stato in grado di refactoring il mio codice. Ora il valore ricevuto dalla prima chiamata ajax può essere utilizzato nella seconda chiamata ajax. Ecco il codice aggiornato:

var userLocation; 

function getUserLocation() { 
    return $.ajax('https://www.example.com/location.json') 
    .then(function(response) { 
    return JSON.parse(response); 
    }).then(function(json) { 
    // data from the location.json file is available here 
    userLocation = json.coordinates; 
    }) 
} 

function getCurrentWeather() { 
    return $.ajax('https://www.example.com/weather' + userLocation + '.json'); 
} 


getUserLocation().then(getCurrentWeather).then(function(data) { 
    // data from the weather(userLocation).json file is available here 
}); 

risposta

8
ajax

di jQuery ritorna promesse, che è possibile utilizzare:

function getUserLocation() { 
    return $.ajax('https://www.example.com/location.json'); // note the `return` 
} 

function getCurrentWeather(userLocation) { 
    return $.ajax('https://www.example.com/weather' + userLocation + '.json'); 
} 

getUserLocation().then(getCurrentWeather).then(function(data) { 
    // location data here 
}); 

O, più verbosely

getUserLocation().then(function (user) { 
    return getCurrentWeather(user); 
}).then(function(data) { 
    // location data here 
}); 

La soluzione migliore sarebbe quella di renderla una singola chiamata, piuttosto che due chiamate da fare un sacco di chiamate AJAX rallenta l'applicazione - in particolare su dispositivi mobili con larghezza di banda limitata.


Qui è un approccio basato su callback che rischia inferiore a quello basato promessa (per esempio con la gestione degli errori) - ma mi sento come dovremmo dimostrare che per completezza. Puoi leggere la soluzione generale in this thread.

function getUserLocation(callback) { 
    $.ajax('https://www.example.com/location.json', callback) 
} 

function getCurrentWeather(userLocation, callback) { 
    $.ajax('https://www.example.com/weather' + userLocation + '.json', callback); 
} 

getUserLocation(function(user) { 
    getCurrentWeather(user, function(weather) { 
     console.log("Got weather", weather); 
    }); 
}); 
+1

Non ho idea del motivo per cui questo codice si trova all'interno di un '$ (documento) .ready' - che rallenta solo le cose senza motivo. –

+0

Ho aggiunto un codice aggiornato in cui ho seguito la soluzione e inoltre ho rimosso il '$ (documento) .ready'. Ho leggermente modificato l'approccio, ad esempio non sto passando l'argomento alla funzione 'getCurrentWeather()'. Raggiunge il risultato desiderato, anche se non sono sicuro che segua una buona pratica. –

+1

Si sta utilizzando lo stato globale mutabile, questo è sbagliato - causerà bug indesiderati ed è molto lontano da una buona pratica. Il problema con questo tipo di codice è il debugging non scrivendolo. –

0

Può essere simile a questo:

var userLocation; 

function getUserLocation() { 
    $.ajax({ 
    url: 'https://www.example.com/location.json', 
    success: function(response) { 
     userLocation = response.coordinates; 
    } 
    }).done(function() { 
     getCurrentWeather() 
    }); 
} 

function getCurrentWeather() { 
    $.ajax({ 
    url: 'https://www.example.com/weather' + userLocation + '.json', 
    success: function(response) { 
     console.log(response); 
    } 
    }); 
} 
+0

pensavo allo stesso modo, ma stavo cercando di staccare la funzione 'getCurrentWeather()' la funzione della 'getUserLocation()' in modo che il codice è più elegante. È possibile? –

+1

@PiotrBerebecki sì, tramite callback o promesse: lo modificherò nella mia risposta. –

1

Per qualche ragione la seconda chiamata restituisce undefined per l'userLocation variabile

Questo è perché non si è restituendo la promessa dalla chiamata Ajax, vedere la risposta di Benjamin su come farlo.

Come posso effettuare il refactoring del mio codice in modo che il valore userLocation della prima chiamata ajax possa essere utilizzato nell'url della seconda chiamata ajax?

refactoring del codice per il nido la chiamata alla altra funzione all'interno della prima chiamata:

var userLocation; 

function getUserLocation() { 
    $.ajax({ 
    url: 'https://www.example.com/location.json', 
    success: function(response) { 
     // set the user location 
     userLocation = response.coordinates; 
     // make call to second function passing in userLocation 
     getCurrentWeather(userLocation); 
    } 
    }); 
} 

function getCurrentWeather(userLocation) { 
    $.ajax({ 
    url: 'https://www.example.com/weather' + userLocation + '.json', 
    success: function(response) { 
     console.log(response); 
    } 
    }); 
} 

$(document).ready(function() { 
    getUserLocation() 
}); 

Se il vostro non si utilizza l'userLocation variabile altrove quindi salvare un po 'di codice:

function getUserLocation() { 
    $.ajax({ 
    url: 'https://www.example.com/location.json', 
    success: function(response) { 
     // make call to second function passing in coordinates from response 
     getCurrentWeather(response.coordinates); 
    } 
    }); 
} 

function getCurrentWeather(userLocation) { 
    $.ajax({ 
    url: 'https://www.example.com/weather' + userLocation + '.json', 
    success: function(response) { 
     console.log(response); 
    } 
    }); 
} 

$(document).ready(function() { 
    getUserLocation() 
}); 
+0

Stavo pensando allo stesso modo, ma stavo cercando di staccare la funzione 'getCurrentWeather()' dalla funzione 'getUserLocation()' in modo che il codice sia più elegante. È possibile? –

+2

Sì, vedere @ Risposta di Benjamin – cnorthfield

1

si dovrebbe fare questo:

function getUserLocation() { 
    return $.ajax({ 
    url: 'https://www.example.com/location.json', 
    success: function(response) { 
     userLocation = response.coordinates; 
    } 
    }); 
} 

function getCurrentWeather(userLocation) { 
    return $.ajax({ 
    url: 'https://www.example.com/weather' + userLocation + '.json', 
    success: function(response) { 
     console.log(response); 
    } 
    }); 
} 


$(document).ready(function() { 
    $.when(
    getUserLocation() 
).done(
    getCurrentWeather 
) 
}); 
  1. ritorno $.ajax(...) da getUserLocation
  2. getCurrentWeather è passato come una funzione, non si dovrebbe chiamare in fatto, sarà chiamato asincrono dopo che getUserLocation è terminato.

Modifica # 2: Cosa si sta facendo male in puting getCurrentWeather() nella .done(...) è che questa funzione chiamerà immediatamente. Tuttavia, .done(...) deve essere passato in una funzione, in cui la funzione verrà chiamata dopo la risoluzione della promessa $.when().

Come Benjamin Gruenbaum accennato, è meglio usare .done(...) poi .then(...)

+0

Il tuo '$ .when' in realtà non fa nulla e il tuo' done' dovrebbe probabilmente essere un 'then'. –

+0

Accetto. Penso che @Piotr Berebecki dovrebbe seguire la tua [risposta] (http://stackoverflow.com/a/36820347/1513547). alleato stava provando a fare solo piccole modifiche sul suo codice originale per sottolineare cosa non stava facendo bene. –

Problemi correlati