如何从promise中返回数据

时间:2016-05-30 21:39:40

标签: javascript angularjs

我需要从承诺中获取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;
}

任何指针都会受到赞赏。

3 个答案:

答案 0 :(得分:33)

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

您可能想要做的是返回整个承诺本身。然后,无论函数需要什么结果,都可以在承诺上调用.then(),结果将在那里承诺已经解决。

以下是来自HTML5Rocks的资源,它遍历承诺的生命周期,以及如何异步解析其输出:
http://www.html5rocks.com/en/tutorials/es6/promises/

答案 1 :(得分:5)

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

不要尝试以承诺作为变量获得结果,当然不可能。但我发现并使用下面的解决方案来访问作为属性的结果。

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

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。我们可以通过某些方式实现这一目标。

  • 在路由器方法中使用resolve:

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

然后在路由器中使用的控制器和其他服务中,只需调用your_factory.theParentId即可获取您的属性。 有关更多信息,请参阅此处: http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx

  • 使用run方法解析您的服务。

    app.run(function (your_factory) { your_factory.addSiteParentId(); })
    
  • 将其注入控制器的第一个控制器或服务中。在控制器中,我们可以调用所有必需的init服务。然后所有保留控制器作为主控制器的子控件可以正常访问此属性。

根据您的上下文选择您的方式取决于变量的范围和变量的读取频率。

答案 2 :(得分:0)

您必须返回承诺而不是变量。 所以在你的函数中只返回:

return relationsManagerResource.GetParentId(nodeId)

然后解决返回的承诺。 或者你可以推迟另一个,并用它解决theParentId