15

No tengo problemas para iniciar sesión o llamar a la API, solo tengo un problema para obtener la respuesta fuera de la devolución de llamada de la API. Sé que funciona de forma asíncrona, por lo que me gustaría ponerlo en una función que devuelva la respuesta. Aquí está mi idea¿Cómo uso una respuesta FB.api (JS SDK) fuera de la función de devolución de llamada?

//What I would like to be able to do 
function fbUser(){ 
    FB.api('/me', function(response){ 
     //this logs the correct object 
     console.log(response); 
    }); 
//How do I get the response out here? 
return response; 
} 

quisiera llamar a la función ME/api una vez al principio y luego pasarlo en torno a mis objetos de vista (sólo tiene que utilizar la respuesta dentro del backbone Visto) y en función de lo que es es necesario hacer otras llamadas de API. Actualmente tengo algunas cosas de trabajo llamando a la vista desde el interior de la devolución de llamada

//What I am doing now, but I lose the ability to pass anything other than the 
//the current response to this function/View 
FB.api('/me', function(response){ 
    var newView = new facebookView({model: response}); 
    }); 

que originalmente estaba tratando de esto, pero debido a que la llamada a la API es asíncrona tuve problemas con las cosas que son indefinidos

//What I started with but had async issues 
var fbResponse; 
FB.api('/me', function(response){ 
    fbResponse = response; 
    }); 
//I would then try and use fbResponse but it would be undefined 

I pierdo la primera respuesta cuando hago el segundo. Por ejemplo, mi primera llamada de API es para/me para obtener la información del usuario. Luego puedo llamar a/your-fb-id/photos y obtener fotos, pero si realizo la llamada a otra función dentro de la devolución de llamada de la API, solo puedo hacer referencia a esa respuesta. Perdí la respuesta original/me. Si pudiera obtener la respuesta de la devolución de llamada, entonces podría aprobarla según sea necesario. Entiendo que la respuesta solo es válida dentro de la devolución de llamada, entonces ¿cómo la hago válida fuera de la devolución de llamada teniendo en cuenta que es asincrónica?

Respuesta

24

OK, todos me di cuenta de esto. Me tomó mucho tiempo y leí muchas páginas diferentes. Lo que dije que quería hacer era lidiar con devoluciones de llamadas y cierres. Primero cubriré el problema de devolución de llamada. Como la función FB.api es asíncrona, nunca se sabe cuándo volverá. Puede detener Javascript o configurar un temporizador, pero esa es una forma horrible de hacer esto. Necesitas una devolución de llamada De hecho, el FB.api está utilizando una devolución de llamada. Eso es lo que es la función anónima como el segundo parámetro. Lo que hice fue crear otra función que llamara a fbUser y usara una devolución de llamada. Esto es lo que hice:

function startThis() { 
    var getUser = fbUser(function(model){ 
     console.log(model); 
     startapp(model); 
    }); 
}; 

function fbUser(callback){ 
     FB.api('/me', function(response){ 
       callback(response); 
      }); 
} 

La función startThis se llama en una respuesta positiva de autenticación de Facebook. Luego llama a la función fbUser que tiene una devolución de llamada. La devolución de llamada devuelve la devolución de llamada desde la función FB.api. Como startThis usa esa devolución de llamada con el valor de retorno llamado modelo, el otro código no se ejecutará hasta que regrese la devolución de llamada. No más problemas indefinidos Estas funciones son solo envoltorios para obtener la respuesta de Facebook a mis puntos de vista. Puede que haya agregado demasiadas capas de abstracción, pero si quieres pasar la respuesta, este es el camino.

En segundo lugar, quería pasar esta respuesta a otra vista. Por ejemplo, una vista carga información básica (usando la respuesta de fbUser). Ahora quiero pasar eso a otra vista que cargue fotos (sé que esto no es MVC de mejores prácticas, pero al usar Facebook no tengo mucho control sobre el Modelo). El problema que tuve fue que no pude pasar la respuesta original a la vista siguiente porque dentro de la función de devolución de llamada para la llamada FB.api this se refiere al Window y no al objeto en el que estaba. Solución: cierres. No explicaré esto a la perfección, pero un cierre es una variable local dentro de una función que todavía tiene una referencia dentro de una función anónima. Aquí está mi solución que debe ilustrar lo que estoy hablando:

photos: function(){ 
      var This = this; 
      var apiString = '/' + this.model.id + '/photos'; 
      FB.api(apiString, function(response){ 
       loadPhoto(response, 1, This.model); 
      }); 

El loadPhoto función es un contenedor para cargar una foto de la visión (lo sé espina dorsal me puede ayudar con la carga de diferentes puntos de vista, pero está abordando un problema a la un momento). Toma la llamada de la foto como modelo, un número como un desplazamiento y la respuesta original. La primera línea de esta función establece esto en una variable local This.Eso me permite, dentro de la función de devolución de llamada anónima, hacer referencia al objeto desde el que se invocó.

Espero que esto pueda ayudar a alguien ya que pasé muchas horas y mucho tiempo de prueba para encontrar la solución a esto. Si no sabe cómo funcionan las devoluciones de llamadas o los cierres, es difícil encontrar la información que está buscando.

+0

¡Gracias! ¡Me ayudó exactamente en la misma situación! –

Cuestiones relacionadas