简体   繁体   English

如何在执行过程中制作角度刷新屏幕

[英]How to make angular refresh screen in the middle of execution

I have a little angular html in a third's page. 我在三分之一的页面中有一点角html。

Everything works fine, the code works fine, the directives work fine (except "ng-show" which never works, but that doesn't matter here). 一切正常,代码正常,指令正常(“ ng-show”除外,该方法永远无效,但是在此无关紧要)。

But I have a heavy code that runs in a button click (with ng-click ). 但是我有一个繁重的代码,可以在按钮单击(使用ng-click )中运行。 During the execution everything freezes, ok, that's expected. 在执行过程中,所有内容都会冻结,这是可以预期的。

But I wish very much to make an "img" appear during the execution, but it seems nothing is updated during the code (everything is perfectly updated after the code, but not during the code). 但是我非常希望在执行过程中出现一个“ img”,但是似乎在代码执行过程中没有任何更新(在代码执行之后,所有内容都完美地更新了,但是代码执行期间却没有更新)。

How can I "refresh" the angular html "during" the execution of the code in "ng-click"? 在“ ng-click”中执行代码期间,如何“刷新”角度html?

I've tried "$scope.apply()" and "$scope.digest()", but both cause some weird errors in the console.... 我已经尝试过“ $ scope.apply()”和“ $ scope.digest()”,但是两者都会在控制台中引起一些奇怪的错误。


EDIT 编辑

Thanks to the answers below: The errors were indeed because the "apply/digest" was already in progress. 由于以下答案:错误确实是因为“应用/摘要”已在进行中。 By using the assynchronous methods shown, I can use "apply" without problems. 通过使用所示的异步方法,我可以毫无问题地使用“应用”。

What about doing an ng-show on an image? 在图像上进行ng-show怎么样? You could use a div that takes up the entire section you wish to show an image with 您可以使用一个div来占据要显示图像的整个部分,

<div ng-show="loading" class="some-class-to-display-image"></div> 

then in your js turn $scope.loading = true; 然后在您的js $scope.loading = true; while you're processing / making calls / etc. You can use a promise and use a .finally() on your requests and set $scope.loading = false; 在处理/拨打电话等过程中,可以使用promise并在请求中使用.finally()并设置$scope.loading = false; to stop the animation. 停止动画。

Wrapping the code you want to execute first in a $scope.apply() should work unless your getting a "$digest already in progress" error which occurs as only one digest cycle can be run at a time. 除非您遇到“ $ digest已经进行中”错误,因为您一次只能运行一个摘要循环,否则应该在$ scope.apply()中包装要首先执行的代码。

If that's the case you could try wrapping the code you want to execute after the loading image is displayed in a $timeout or $evalAsync(Angular v1.2.x & above) which will make sure the 2 digest cycles don't collide ie 如果是这种情况,您可以尝试在$ timeout或$ evalAsync(Angular v1.2.x及以上)中显示加载图像后包装要执行的代码,以确保2个摘要周期不会冲突,即

    $scope.$apply(function () {
        //display loading image code
    });
    //Other code

or 要么

    //display loading image code
    $scope.$evalAsync(function () {
        //Other code
    });

The way JavaScript works in a browser environment is that one block of javascript is executed until it is finished, the browser does not render intermediate results regardless if you use AngularJS or vanilla JavaScript. JavaScript在浏览器环境中的工作方式是执行一块JavaScript直到完成为止,无论您使用AngularJS还是普通JavaScript,浏览器都不会呈现中间结果。

Example

Let's assume you do heavy lifting on 10.000 data entries and want to show a progress bar: 假设您对10.000个数据条目进行了繁重的操作,并希望显示进度条:

startButton.onclick = function onStartClick() {
  var progressbar = document.getElementById('progressbar');
  progressbar.style.width = "0";

  // process 100000 entries, update progress bar between
  for (var n = 0; n < 100000; y++) {
    doSomethingWithEntryNumber(n);
    progressbar.style.width = (n / 100000) + "%";
  }
}

It will not update the progressbar div in the browser as might be intended, but will freeze the browser until onDivClick is finished. 它不会按预期更新浏览器中的progressbar div ,但会冻结浏览器,直到onDivClick完成。 This is no different for AngularJS, where processing lots of data will not update your UI. 这对于AngularJS来说没有什么不同,在AngularJS中处理大量数据不会更新您的UI。

To process a large amount of data, you need to split the work and use any kind of "future"/"promise"/"delay" technique - for this example: 要处理大量数据,您需要拆分工作并使用任何类型的“未来” /“承诺” /“延迟”技术-对于此示例:

startButton.onclick = function onStartClick() {
  var progressbar = document.getElementById('progressbar');
  progressbar.style.width = "0";

  // process 100000 entries in 1000 entry batches, update progress bar between
  function processBatch(batch) {
    for (var i = 0; i < 1000; i++) {
      doSomethingWithEntryNumber(batch*1000 + i);
    }
    // update progressbar
    progressbar.style.width = (batch / 1000) + "%";
    if (batch < 99) {
      // continue work after browser has updated UI
      setTimeout(processBatch.bind(this, batch + 1), 10);
    }
  }
  processBatch(0);
}

This way the browser can render UI changes, the user can scroll, etc. while you are still able to process your 100000 data entries. 这样,浏览器可以呈现UI更改,用户可以滚动等,同时您仍然可以处理100000个数据条目。

In respect to "showing an image during the process", you would show the image, then setTimeout to do your work delayed, when your work is finished remove the image and set your data to the $scope . 关于“在处理过程中显示图像”,您将显示图像,然后setTimeout延迟您的工作,当您完成工作后,删除图像并将数据设置为$scope

You cannot refresh the HTML "during" the execution, as a web page in mono-threaded, which means when the CPU is computing, nothing else can be done. 您无法在执行过程中刷新HTML,因为Web页面是单线程的,这意味着当CPU正在计算时,无法执行其他任何操作。 (Technically web workers can help forking multiple threads but really, you do not need that). (从技术上讲,网络工作者可以帮助派生多个线程,但实际上,您不需要这样做)。

So what you want on click is say, enable an image, then wait for angular to update the DOM with that image, and then run your heavy code. 因此,您要单击的就是说,启用一个图像,然后等待angular用该图像更新DOM,然后运行繁重的代码。

To achieve that you need to use the $timeout service, this way: 要实现这一点,您需要使用$timeout服务,方法是:

$scope.onClick = function() {
  // Set the model to display an image
  $scope.displayImage = true;
  // Wait for angular to digest the current cycle and update the DOM
  $timeout(function() {
    // Do heavy stuff, and at the bottom of the code update the model to hide the image
    $scope.doHeavyStuff();
    $scope.displayImage = false;
  });
}

In your HTML you simply need 在您的HTML中,您只需要

<img ng-show = "displayImage" src = "some_url">
<div ng-hide = "displayImage"> Heavy stuff done :) </div>

Now if you have a problem with ng-show at this step, please open a different question. 现在,如果您在此步骤上遇到ng-show问题,请打开另一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM