【问题标题】:Issue with asynchronous call in Angular JSAngular JS中的异步调用问题
【发布时间】:2018-05-09 10:18:53
【问题描述】:

在我的 Angular 应用中,在以下场景中,我遇到了问题。

一共有三个文件

ma​​inCtrl.js

在应用程序加载时,init() mainCtl.js 将被触发,它将像这样调用 flowService

flowService.configureSteps();

它将调用 flowService 并调用服务器来获取数据。

flowService.js

function configureSteps() {
    salesService.getSalesOrder().then(function(response) {
            salesService.setSalesOrder(response);
    });
}

这会将salesOrder 保存到要在subCntrl 中检索的服务中

subCtrl.js

在 subCntrl 的初始化中,我试图获取我保存在服务中的 salesOrder。

function init() {
   salesService.getSalesOrder();
}

问题

当我像这样点击网址时

http://www.myapp.com/review#/subpage
  1. 它会打到mainCtrl
  2. 它会从那里调用服务并调用服务器
  3. 由于是异步的,所以会被重定向到subCntrl
  4. 它将尝试检索尚未从服务器接收到的 salesOrder。

如何实现同步。 ?

【问题讨论】:

  • 您可以让 getSalesOrder 返回一个 Promise,该 Promise 解决一次(或如果)setSalesOrder 被调用。你不make it synchronous - 你更改你的代码来处理异步。
  • How can this be made synchronous? 不能。如果可以,它不应该。你倒着想。与其试图按照自己的方式改变事物,不如学习如何处理异步并接受它的力量。
  • @JeremyThille 您能否建议以哪种方式处理这种情况。 ?
  • @CertainPerformance 你的意思是使用 $q 服务?
  • subCntrl 是如何在流程中被调用的?可能有一种方法肯定会奏效,但我需要了解流程

标签: javascript angularjs ajax asynchronous


【解决方案1】:

使用事件让subCtrl.js 知道该值已被接收。现在,由于它还在$digest循环下运行,所以你可以轻松处理subCtrl.js的UI。在控制器和服务中注入$rootScope

flowService.js

function configureSteps() {
    salesService.getSalesOrder().then(function(response) {
            salesService.setSalesOrder(response);
            $rootScope.$emit('order-recieved');
    });
}

subCtrl.js

function init() {
   $rootScope.$on('order-recieved',function(){
      salesService.getSalesOrder();
   })
}

【讨论】:

  • 是的,我已经尝试过了。这将起作用。但我有另一种情况,网址中不会有 #/subpage 。在这种情况下,我手动重定向到 subPage。在这种情况下,$rootScope.$on 将不可用,因为 subPage.js 未在浏览器中呈现。
  • @I'mnidhin 你能创建一个小 plunkr 来复制你的场景吗?它将帮助我更好地理解它并提供带有工作代码的建议。
  • ok.. 我们可以返回一个 promise 并在控制器中使用它吗?
【解决方案2】:

您可以将 ma​​inCtrl.js flowService.configureSteps() 调用移至:

  1. 解决状态函数 (UI-Router)
  2. $routeChangeStart 事件回调 (NgRoute)

使用 UI-Router 状态,您可以设置一个解析函数,该函数将在 访问引用的状态之前执行,从而可以在该状态的实例化之前执行 同步 的事情控制器。

在您的情况下,您可以在访问 ma​​inCtrl 之前执行 flowService.configureSteps() 并在访问 subCtrl 之前执行 salesService.getSalesOrder() (但肯定是在上一个订单保存之后) .


使用 ngRoute,您可以将 routeChange 回调定义为:

$rootScope.$on("$routeChangeStart", function (event, currentRoute, previousRoute) {
    //
}); 

在此回调中,您可以在路由激活之前执行您的逻辑,确保在您点击页面时获得所需的内容。


如果您需要进一步的帮助,请分享您的路线/状态配置。

【讨论】:

    【解决方案3】:

    我已经使用 promise 实现了。

    flowService.js

     function configureSteps() {
            var salesPromise = salesService.getSalesOrder().then(function(response) {
                    salesService.setSalesOrder(response);
            });
            return salesPromise ;
        }
    
    salesService.setPromise(configureSteps()); // Saves the promise to a service
    

    subCtrl.js

    function init() {
     salesService.getPromise().then(function() {
           salesService.getSalesOrder(); // This will be called only on resolve of the promise.
        });
    
    }
    

    在服务中写入setPromisegetPromise

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-24
      • 2016-04-07
      • 1970-01-01
      • 2011-03-16
      • 1970-01-01
      • 2018-04-24
      • 2016-03-07
      • 2022-01-25
      相关资源
      最近更新 更多