¿Dónde se almacena la respuesta después de una solicitud de Dojo JSONP?
Pregunta
Javascript
Por ejemplo, tengo el siguiente código JavaScript (Dojo 1.6 ya está cargado):
dojo.require("dojo.io.script")
// PART I
var jsonpArgs = {
url: "http://myapp.appspot.com/query",
content: {
id: "1234",
name: "Juan",
start_date: "2000-01-01",
callback: "recover"
}
};
// PART II
dojo.io.script.get(jsonpArgs).then(function(data) {
console.log(data);
});
// PART III
function recover(data) {
console.log(data);
}
Consulta directa del navegador
Entiendo que mi servidor recibirá la consulta como si hubiera escrito lo siguiente en la barra de direcciones:
http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=recover
Respuesta esperada
Si consulté directamente mi servidor usando la barra de direcciones del navegador, recibiré, en tipo mime application/json
y texto sin formato renderizado en el navegador, algo como esto:
recover(
{
id: 1234,
name: Juan,
data: [
["2000-01-01", 1234],
["2000-01-02", 5678]
]
}
);
Problema
Ahora, mirando hacia atrás a la Parte II del JavaScript, ejecutaría la solicitud JSONP con dojo.io.script.get(jsonpArgs)
. Esto devuelve un Deferred
objeto, que puedo aprovechar encadenando .then
después de. Tenga en cuenta que definí el manejador para el .then
Evento a la producción que capturó data
a la consola.
Sin embargo, todo lo que obtengo en la consola es un Event
. Traté de buscar en su árbol de datos, pero no pude encontrar los datos que esperaba.
Pregunta
- ¿Dónde se almacena la respuesta para una solicitud JSONP? ¿Cómo lo encuentro?
- Mi servidor (que controlo) solo genera una representación de texto sin formato de los datos solicitados, envuelto en el
callback
función (aquí especificada comorecover
), y especifica unapplication/json
Tipo de Mimica. ¿Hay algo más que necesite configurar en mi servidor, de modo que los datos de respuesta sean capturados por elDeferred
¿objeto?
Intento de solución
De hecho, puedo recuperar la respuesta definiendo la función de devolución de llamada (en este caso recover
en la Parte III del JavaScript). Sin embargo, en los tutoriales del dojo, simplemente recuperaron los datos utilizando el Deferred
(y .then
) estructura. ¿Cómo lo hago usando dojo? Deferred
¿s?
Actualización (usando el ejemplo de Twitter del tutorial de Dojo)
Tome, por ejemplo, este guión del tutorial de Dojo, Conseguir Jiggy con JSONP. Lo edité para registrar datos en la consola.
dojo.require("dojo.io.script");
dojo.io.script.get({
url: "http://search.twitter.com/search.json",
callbackParamName: "callback",
content: {q: "#dojo"}
}).then(function(data){
//we're only interested in data.results, so strip it off and return it
console.log(data); // I get an Object, not an Event, but no Twitter data when browsing the results property
console.log(data.results) // I get an array of Objects
return data.results;
});
Para console.log(data)
, Obtengo un Object
, no un Event
como lo ilustra mi caso. Dado que el ejemplo implica que los datos residen en data.results
, También trato de navegar por este árbol, pero no veo mis datos esperados de Twitter. Estoy perdido.
Para console.log(data.results)
, Obtengo una variedad de Object
s. Si consulte Twitter directamente, esto es lo que obtendría en texto sin formato. Cada Object
Contiene los metadatos de tweet habituales como el nombre de usuario, el tiempo, el retrato de usuario y el tweet en sí. Suficientemente fácil.
Este me golpea directamente en la cabeza. El manejador para el .then
la cadena, una función anónima, recibe solo un argumento data
. Pero, ¿por qué es que el results
propiedad de console.log(data)
y el objeto devuelto del que obtengo console.log(data.results)
son diferente?
Solución
Lo tengo.
Implementación de devolución de llamada manual
function recover(data) {
console.log(data);
}
var jsonpArgs = {
url: "http://myapp.appspot.com/query",
content: {
id: "1234",
name: "Juan",
start_date: "2000-01-01",
callback: "recover"
};
dojo.io.script.get(jsonpArgs);
Esta es la solicitud que reciba mi servidor:
http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=recover
En este caso, esperaré la siguiente salida de mi servidor:
recover({
id: 1234,
name: Juan,
data: [
["2000-01-01", 1234],
["2000-01-02", 5678]
]
});
Tres cosas a tener en cuenta:
- El servidor esperará
callback
En la cadena URL de consulta.callback
se implementa como una propiedad dejsonpArgs
. - Porque especifiqué
callback=recover
, mi servidor se adjuntarárecover(
+the_data_I_need
+)
, devuelve la cadena completa al navegador, y el navegador se ejecutarárecover(the_data_I_need)
. Esto significa... - Que tendré que definir, por ejemplo,
function recover(one_argument_only) {doAnythingYouWantWith(one_argument_only)}
El problema con este enfoque es que no puedo aprovechar Deferred
encadenado usando .then
. Por ejemplo:
dojo.io.script.get(jsonpArgs).then(function(response_from_server) {
console.log(response_from_server);
})
Esto me dará un Event
, sin rastro de la respuesta esperada en absoluto.
Aprovechando la implementación de Dojo de las solicitudes JSONP
var jsonpArgs = {
url: "http://myapp.appspot.com/query",
callbackParamName: "callback",
content: {
id: "1234",
name: "Juan",
start_date: "2000-01-01"
};
dojo.io.script.get(jsonpArgs);
Esta es la solicitud que reciba mi servidor:
http://myapp.appspot.com/query?id=1234&name=Juan&start_date=2000-01-01&callback=some_function_name_generated_by_dojo
En este caso, esperaré la siguiente salida de mi servidor:
some_function_name_generated_by_dojo({
id: 1234,
name: Juan,
data: [
["2000-01-01", 1234],
["2000-01-02", 5678]
]
});
Cosas a tener en cuenta:
Tenga en cuenta la propiedad de
jsonpArgs
,callbackParamName
. El valor de esta propiedad debe ser el nombre de la variable (en la cadena URL de consulta) esperada por el servidor. Si mi servidor esperacallbackfoo
, despuéscallbackParamName: "callbackfoo"
. En mi caso, mi servidor espera el nombrecallback
, por lo tantocallbackParamName: "callback"
.En el ejemplo anterior, especifiqué en la URL de consulta
callback=recover
y procedió a implementarfunction recover(...) {...}
. Esta vez, no necesito preocuparme por eso. Dojo insertará su propia función preferidacallback=some_function_name_generated_by_dojo
.Imagino
some_function_name_generated_by_dojo
ser definido como:
Definición:
function some_function_name_generated_by_dojo(response_from_server) {
return response_from_server;
}
Por supuesto, la definición no es tan simple, pero la ventaja de este enfoque es que puedo aprovechar el marco diferido de Dojo. Vea el código a continuación, que es idéntico al ejemplo anterior:
dojo.io.script.get(jsonpArgs).then(function(response_from_server) {
console.log(response_from_server);
})
Esto me dará los datos exactos que necesito:
{
id: 1234,
name: Juan,
data: [
["2000-01-01", 1234],
["2000-01-02", 5678]
]
}