Javascript 如何从promise返回数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37533929/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 20:26:14  来源:igfitidea点击:

How to return data from promise

javascriptangularjs

提问by Craig

I need to get the response.dataout of the promise so it can be returned by the enclosing function. I know, I probably can't do it the way I've coded it because of normal JavaScript scope. Is there any way, it can be done?

我需要response.data摆脱承诺,以便它可以由封闭函数返回。我知道,由于正常的 JavaScript 范围,我可能无法按照我编码的方式来完成。有什么办法,可以做到吗?

The console.logat #1 produces the correct data. console.log#2 always produces 'a';

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

Any pointers would be appreciated.

任何指针将不胜感激。

回答by Maximillian Laumeister

One of the fundamental principles behind a promise is that it's handled asynchronously. This means that you cannot create a promise and then immediately use its result synchronously in your code (e.g. it's not possible to return the result of a promise from within the function that initiated the promise).

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

What you likely want to do instead is to return the entire promise itself.Then whatever function needs its result can call .then()on the promise, and the result will be there when the promise has been resolved.

您可能想做的是返回整个承诺本身。然后任何需要其结果的函数都可以调用.then()承诺,当承诺得到解决时,结果就会在那里。

Here is a resource from HTML5Rocks that goes over the lifecycle of a promise, and how its output is resolved asynchronously:
http://www.html5rocks.com/en/tutorials/es6/promises/

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

回答by Vu Quyet

I also don't like using a function to handle a property which has been resolved again and again in every controller and service. Seem I'm not alone :D

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

Don't tried to get result with a promise as a variable, of course no way. But I found and use a solution below to access to the result as a property.

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

Firstly, write result to a property of your service:

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

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

Now, we just need to ensure that method addSiteParentIdalways be resolved before we accessed to property theParentId. We can achieve this by using some ways.

现在,我们只需要确保addSiteParentId在访问 property 之前始终解析该方法theParentId。我们可以通过使用一些方法来实现这一点。

  • Use resolve in router method:

    resolve: {
        parentId: function (your_factory) {
             your_factory.addSiteParentId();
        }
    }
    
  • 在路由器方法中使用解析:

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

then in controller and other services used in your router, just call your_factory.theParentId to get your property. Referce here for more information: http://odetocode.com/blogs/scott/archive/2014/05/20/using-resolve-in-angularjs-routes.aspx

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

  • Use runmethod of app to resolve your service.

    app.run(function (your_factory) { your_factory.addSiteParentId(); })
    
  • Inject it in the first controller or services of the controller. In the controller we can call all required init services. Then all remain controllers as children of main controller can be accessed to this property normally as you want.

  • 使用run应用程序的方法来解决您的服务。

    app.run(function (your_factory) { your_factory.addSiteParentId(); })
    
  • 将其注入到第一个控制器或控制器的服务中。在控制器中,我们可以调用所有需要的初始化服务。然后所有作为主控制器子级的控制器都可以根据需要正常访问此属性。

Chose your ways depend on your context depend on scope of your variable and reading frequency of your variable.

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

回答by Mehdi Seifi

You have to return a promiseinstead of a variable. So in your function just return:

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

return relationsManagerResource.GetParentId(nodeId)

And later resolve the returned promise. Or you can make another deferred and resolve theParentIdwith it.

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