如何从承诺中返回数据

问题描述:

我需要将response.data取出承诺,以便可以通过封闭函数返回。我知道我可能无法按照我编写它的方式进行编写,因为它的JavaScript范围正常。有什么办法可以做到吗?如何从承诺中返回数据

#1处的console.log会生成正确的数据。 console.log#2总是产生'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; 
} 

任何指针,将不胜感激。

+0

你费心寻找现有的关于这个问题吗? – Amit

+1

否 - 你不能 - 你想用'response'完成的操作必须放在'.then()'处理程序中。您不能在同步样式中编写异步JavaScript! – slugonamission

+1

这不是关于从承诺中返回数据。 第二个'console.log'发生在承诺设置'theParentId'变量之前 - 因为承诺是异步而'console.log'不是。 – JordanHendrix

承诺背后的基本原则之一是它是异步处理的。这意味着您不能创建承诺,然后立即在代码中同步使用其结果(例如,不可能从启动承诺的函数内返回承诺的结果)。

你可能想要做的是返回整个承诺本身。然后,无论需要什么样的功能,其结果都可以在承诺上打电话.then(),当承诺解决后,结果将在那里。

这里是一个的HTML5Rocks的资源,越过一个承诺的生命周期,以及如何将其输出异步解决:
http://www.html5rocks.com/en/tutorials/es6/promises/

+1

非常感谢您的温柔指导。我知道这与我接触它的方式有关。我对Angular很陌生,因此碰到了一堵砖墙。它现在正在工作,但恐慌结束后可能会进一步完善。再次感谢你提供的建议。 – Craig

你必须返回一个承诺,而不是一个变量。 所以在你的功能只是返回:

return relationsManagerResource.GetParentId(nodeId) 

而后解决返回的承诺。 或者您可以使其他人推迟并使用它解析theParentId

我也不喜欢使用一个函数来处理一个已经在每个控制器和服务中一次又一次解决的属性。看来我并不孤单:D

不要试图得到一个承诺作为一个变量的结果,ofcourse没办法。但是我发现并使用了下面的解决方案来访问作为属性的结果。

首先,结果写入到您的服务的属性:

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 
      });      
    }   
}) 

现在,我们只需要确保方法addSiteParentId之前,我们访问的财产theParentId总是可以解决。我们可以通过一些方式来实现这一点。

  • 使用决心路由器方法:

    决心:{ parentId的:函数(your_factory){ your_factory.addSiteParentId(); }}

然后在控制器和你的路由器使用的其他服务,只需拨打your_factory.theParentId让你的财产。 Referce这里了解更多信息: http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx

  • 使用“运行”应用程序的方法来解决你的服务。

    app.run(函数(your_factory){your_factory.addSiteParentId();})

  • 注入它在所述控制器的第一控制器或服务。在控制器中,我们可以调用所有需要的init服务。然后,所有作为主控制器的子控制器的控制器都可以正常访问该属性。

选择你的方式取决于你的上下文取决于你的变量的范围和你的变量的阅读频率。对一个承诺返回数据

一种方法是这样

const addSiteParentId = (nodeId) => { 
    const data = { theParentId: "" } 
    relationsManagerResource.GetParentId(nodeId).then((response)=> Object.assign(data, data.theParentId, response.data)/* #1 */); 
    return data.theParentId; 
} 
// Object.assign do this magic 
console.log("theParentId:", addSiteParentId(nodeId)) 

Object.assign:https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

+0

虽然这段代码可能会回答这个问题,但提供关于为什么和/或代码如何回答问题的其他内容可以提高其长期价值。 –

+0

谢谢@DonaldDuck –