Cómo devolver datos de la promesa [duplicado]

68

Necesito response.datasalir de la promesa para que la función adjunta pueda devolverla. Lo sé, probablemente no pueda hacerlo de la forma en que lo he codificado debido al alcance normal de JavaScript. ¿Hay alguna forma de hacerlo?

El archivo console.log en el n. ° 1 produce los datos correctos. console.log # 2 siempre produce 'a';

function addSiteParentId(nodeId) {   
    var theParentId = 'a';
    var parentId = relationsManagerResource.GetParentId(nodeId)
                        .then(function(response){                               
                            theParentId = response.data;
                            console.log(theParentId);  // #1
                        });
    console.log(theParentId);  // #2
    return theParentId;
}

Cualquier indicador sería apreciada.

3
  • 3
    No, no puede, las operaciones que desee realizar responsedeben ir en el .then()controlador. ¡No puede escribir Javascript asincrónico en un estilo sincrónico! 30 de mayo de 2016 a las 21:43
  • 2
    No se trata de devolver datos de una promesa. El segundo console.logocurre antes de que la promesa establezca la theParentIdvariable, porque la promesa es asíncrona, mientras que la promesa console.logno lo es.
    omarjmh
    30 de mayo de 2016 a las 21:44
  • 1
    @Amit, sí lo hice, pero solo hubo quejas acerca de que la pregunta no era lo suficientemente específica, lo cual era cierto.
    Craig
    30 de mayo de 2016 a las 23:22
82

Uno de los principios fundamentales detrás de una promesa es que se maneja de forma asincrónica. Esto significa que no puede crear una promesa y luego usar inmediatamente su resultado sincrónicamente en su código (por ejemplo, no es posible devolver el resultado de una promesa desde la función que inició la promesa).

Lo que probablemente quiera hacer en su lugar es devolver la promesa completa. Entonces, cualquier función que necesite su resultado puede invocar .then()la promesa, y el resultado estará allí cuando la promesa se haya resuelto.

Aquí hay un recurso de HTML5Rocks que repasa el ciclo de vida de una promesa y cómo su salida se resuelve de forma asincrónica:
https://web.dev/promises/

4
  • 8
    Muchas gracias por la amable orientación. Sabía que tendría algo que ver con la forma en que lo abordé. Soy muy nuevo en Angular, así que estaba golpeando una pared de ladrillos. Ahora está funcionando, pero probablemente se pueda refinar aún más una vez que pase el pánico. Gracias otra vez por el consejo.
    Craig
    30 de mayo de 2016 a las 23:20
  • 1
    @Maximillian Sugeriría que responder a la pregunta tal como se hizo también tendría valor. 7 abr.20 a las 11:22
  • @donothingsuccessfully Por lo que puedo decir, respondí la pregunta tal como se hizo. 8 abr.20 a las 20:04
  • @Maximillian disculpas 9 abr.20 a las 10:35
9

Tampoco me gusta usar una función para manejar una propiedad que se ha resuelto una y otra vez en cada controlador y servicio. Parece que no estoy solo: D

No intente obtener un resultado con una promesa como variable, por supuesto, de ninguna manera. Pero encontré y uso una solución a continuación para acceder al resultado como una propiedad.

En primer lugar, escriba el resultado en una propiedad de su servicio:

app.factory('your_factory',function(){
    var theParentIdResult = null;
    var factoryReturn = {  
        theParentId: theParentIdResult,
        addSiteParentId : addSiteParentId
    };
    return factoryReturn;
    function addSiteParentId(nodeId) {   
         var theParentId = 'a';
         var parentId = relationsManagerResource.GetParentId(nodeId)
             .then(function(response){                               
                 factoryReturn.theParentIdResult = response.data;
                 console.log(theParentId);  // #1
             });                    
    }        
})

Ahora, solo necesitamos asegurarnos de que el método addSiteParentIdsiempre se resuelva antes de acceder a la propiedad theParentId. Podemos lograr esto usando algunas formas.

  • Utilice resolver en el método del enrutador:

    resolve: {
        parentId: function (your_factory) {
             your_factory.addSiteParentId();
        }
    }
    

luego, en el controlador y otros servicios utilizados en su enrutador, simplemente llame a your_factory.theParentId para obtener su propiedad. Consulte aquí para obtener más información: http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx

  • Utilice el runmétodo de aplicación para resolver su servicio.

    app.run(function (your_factory) { your_factory.addSiteParentId(); })
    
  • Inyectarlo en el primer controlador o servicios del controlador. En el controlador podemos llamar a todos los servicios init requeridos. Entonces, todos siguen siendo controladores, ya que los hijos del controlador principal pueden acceder a esta propiedad normalmente como desee.

Elija sus formas dependerá de su contexto, dependerá del alcance de su variable y la frecuencia de lectura de su variable.

1

Tienes que devolver una promesa en lugar de una variable. Entonces en su función simplemente regrese:

return relationsManagerResource.GetParentId(nodeId)

Y luego resolver la promesa devuelta. O puede hacer otro aplazado y resolverlo theParentId.