【问题标题】:How to return data from promise [duplicate]如何从承诺返回数据[重复]
【发布时间】:2021-04-18 18:31:14
【问题描述】:

我需要将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;
}

任何指针将不胜感激。

【问题讨论】:

  • 不——你不能——你想对response做的任何操作都必须在.then()处理程序中。你不能以同步的方式编写异步 Javascript!
  • 这不是关于从承诺中返回数据。第二个console.log 发生在promise 设置theParentId 变量之前——因为promise 是异步的,而console.log 不是。
  • @Amit,是的,我做到了,但只有抱怨这个问题不够具体,这是真的。

标签: javascript angularjs


【解决方案1】:

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

您可能想要做的是返回整个promise本身。然后任何需要其结果的函数都可以在promise上调用.then(),当promise有结果时就会出现已解决。

以下是 HTML5Rocks 中的一个资源,它涵盖了 Promise 的生命周期,以及它的输出是如何异步解析的:
https://web.dev/promises/

【讨论】:

  • 非常感谢您的温柔指导。我知道这与我接近它的方式有关。我对 Angular 很陌生,所以碰到了一堵砖墙。它现在正在工作,但一旦恐慌结束,可能会进一步完善。再次感谢您的建议。
  • @Maximillian 我建议按要求回答问题也很有价值。
  • @donothingsuccessfully 据我所知,我确实按要求回答了这个问题。
  • @Maximillian 道歉
【解决方案2】:

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

不要试图用promise作为变量来获取结果,当然没办法。但我发现并使用下面的解决方案将结果作为属性访问。

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

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

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

  • 在路由方法中使用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(); })
    
  • 将其注入到第一个控制器或控制器的服务中。在控制器中,我们可以调用所有必需的初始化服务。那么作为主控制器的子控制器的所有剩余控制器都可以正常访问该属性。

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

【讨论】:

    【解决方案3】:

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

    return relationsManagerResource.GetParentId(nodeId)
    

    然后解决返回的承诺。 或者你可以再做一个 deferred 并用它解决theParentId

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-22
      • 2015-11-04
      • 2016-10-20
      相关资源
      最近更新 更多