New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make $digest async #7548

Closed
wants to merge 7 commits into
base: master
from

Conversation

Projects
None yet
7 participants
@vnesterovsky
Copy link

vnesterovsky commented May 22, 2014

Request Type: refactor

How to reproduce:

Component(s): scope

Impact: large

Complexity: medium

This issue is related to:

Detailed Description:

We think it's important to lesser the stress on $digest in angular, thus
we suggest to refactor $digest implementation, and make it asynchronous.

Other Comments:

With this in mind we've introduced several changes in our branch.

  1. $q service is extended with several methods to support building of asynchronous algorithms.
    These are:
    promise.thenIf();
    promise.thenWhile();
    promise.thenDoWhile();
    promise.thenForEach();
    promise.thenFor();
    $q.run();

    In theory we would prefer to refactor this service more greatly but we decided to introduce minimal additions there.

  2. Introduces $scheduler service that provides:
    a) nextTick() a implementation to runs deferred objects in batches until they fit in a time slot, and
    then continue the remaining part after some sleep;
    b) q factory;

  3. rootScope's $digest(), $watchCollection(), and ngRepeater's watch action logics are refactored.

  4. schedulerSpec, and asyncDigestSpec tests are created.
    Some other tests are fixed.

  5. rootScopeProvider has asyncDigest property (false is default) to preserve backward compatibility.

@mary-poppins

This comment has been minimized.

Copy link

mary-poppins commented May 22, 2014

Thanks for the PR! Please check the items below to help us merge this faster. See the contributing docs for more information.

  • Uses the issue template (#7548)

If you need to make changes to your pull request, you can update the commit with git commit --amend.
Then, update the pull request with git push -f.

Thanks again for your help!

@IgorMinar IgorMinar added this to the Purgatory milestone May 22, 2014

@IgorMinar

This comment has been minimized.

Copy link
Member

IgorMinar commented May 22, 2014

Hi Vladimir,

This is a crazy big change without any explanation as to what the motivation is and why this approach is significantly better than other approaches for common scenarios.

It's apparent that you needed this change for some project you are working on, so I'd like to hear how did you apply it there and what the results were.

@mary-poppins

This comment has been minimized.

Copy link

mary-poppins commented May 22, 2014

I'm sorry, but I wasn't able to verify your Contributor License Agreement (CLA) signature. CLA signature is required for any code contributions to AngularJS.

Please sign our CLA and ensure that the CLA signature email address and the email address in this PR's commits match.

If you signed the CLA as a corporation, please let us know the company's name.

Thanks a bunch!

PS: If you signed the CLA in the past then most likely the email addresses don't match. Please sign the CLA again or update the email address in the commit of this PR.
PS2: If you are a Googler, please sign the CLA as well to simplify the CLA verification process.

@vnesterovsky vnesterovsky added cla: no and removed cla: yes labels May 22, 2014

@vnesterovsky

This comment has been minimized.

Copy link

vnesterovsky commented May 22, 2014

Hello, Igor!

Thank you for your attention to our request.

The change we propose is a result of a meantime failed attempt to integrate (and then incrementally migrate to) with angular of some enterprise application developed with kendoui.

The problem was that the model at that application at times may contain several thousands objects.
kendoui has no problem at all with such model, in contrast to angular, which freezed the application.

We know internet is full with workarounds and design patterns against "big" model problem in angular. We think, however, that the "key word" here is a "workaround". Angular developers have to apply efforts to avoid "big" view model.

That's as for background.

As for the scope of change.
We suggest, in fact, two features:

  1. API based on $q service to allow write (refactor) long running javascript.
    A script is scheduled to run on limited time slices, which makes whole application
    much more responsive. At the same time script itself will progress more slowly.

    The API is implemented in q.js and in scheduler.js.
    It's pure library extension, and should not impact any application.

    1. Refactoring of $digest() and of some of its dependencies.
      We agree that this might have an impact, and any changes need to be carefully verified.
      Unit tests help there.

      The good point is that it's relatively easy to refactor regular algorithm into async one.
      Consider original code:

// copy the items to oldValue and look for changes.
for (var i = 0; i < newLength; i++) {
  var bothNaN = (oldValue[i] !== oldValue[i]) && (newValue[i] !== newValue[i]);
  if (!bothNaN && (oldValue[i] !== newValue[i])) {
    changeDetected++;
    oldValue[i] = newValue[i];
  }
}
return changeDetected;

vs refactored one:

// copy the items to oldValue and look for changes.
// ...
thenFor(
  function() { i = 0; },
  function() { return i < newLength; },
  function() { i++; },
  function() {
    var bothNaN = (oldValue[i] !== oldValue[i]) && (newValue[i] !== newValue[i]);
    if (!bothNaN && (oldValue[i] !== newValue[i])) {
      changeDetected++;
      oldValue[i] = newValue[i];
    }
  }).then(function() {
    return changeDetected;
  });

In addition, we refactored code like that to allow to run $digest() synchronously (by default), which should minimize an impact.

That's as for technical part.

@vnesterovsky

This comment has been minimized.

Copy link

vnesterovsky commented May 22, 2014

I've just filled and sent CLA form.

On response I got:
"
code.google.com signatories
Thank you. Your CLA submission will be processed shortly.
"
Should I take some other action?

@vnesterovsky vnesterovsky reopened this May 22, 2014

@mary-poppins

This comment has been minimized.

Copy link

mary-poppins commented May 22, 2014

CLA signature verified! Thank you!

Someone from the team will now triage your PR and it will be processed based on the determined priority (doc updates and fixes with tests are prioritized over other changes).

@IgorMinar IgorMinar removed the cla: no label May 23, 2014

{
key = (collection === collectionKeys) ? index : collectionKeys[index];
value = collection[key];
trackById = trackByIdFn(key, value, index);

This comment has been minimized.

@Fresheyeball

Fresheyeball May 28, 2014

Contributor

why you no var?

This comment has been minimized.

@vnesterovsky

vnesterovsky May 28, 2014

There is var!

Please see code above:
$scope.$watchCollection(rhs, function ngRepeatAction(collection){
var index, length,
...
arrayLength,

This is as it was before the change.
Please note that the goal was to refactor potentially long running piece of code into async one, but at the same time to leave it recognizable.

@btford btford removed the gh: PR label Aug 20, 2014

@caitp caitp force-pushed the angular:master branch from 591bac5 to d713ad1 Aug 22, 2014

@tbosch tbosch force-pushed the angular:master branch from 6c27b89 to 271572c Aug 30, 2014

@tbosch tbosch force-pushed the angular:master branch from a3d7934 to 1418383 Sep 10, 2014

@petebacondarwin petebacondarwin force-pushed the angular:master branch from 02dc2aa to fd2d6c0 Sep 16, 2014

@jeffbcross jeffbcross force-pushed the angular:master branch 2 times, most recently from cad9560 to f294244 Sep 27, 2014

@btford btford force-pushed the angular:master branch from 9011a65 to 46db47b Oct 6, 2014

@jeffbcross jeffbcross force-pushed the angular:master branch 4 times, most recently from e8dc429 to e83fab9 Oct 8, 2014

@petebacondarwin petebacondarwin force-pushed the angular:master branch from 4dd5a20 to 998c61c Oct 19, 2014

@caitp

This comment has been minimized.

Copy link
Contributor

caitp commented Jan 6, 2015

the ideas presented are interesting, but in its current form I don't think we can do much with this.

I've proposed a new launch process for massive changes like this, and I invite you to participate in the launch process so that we can thoroughly discuss changes like this, and talk about their benefits, caveats, and impact on other peoples applications. The goal is to come up with something which best lines up with Angular's goals as a framework, and makes the most users happy (by making it easier for them to write their applications, and making their applications better).

The basic idea is, I'd like you to put together a design document explaining in detail the workings of your changes, provide arguments for why the change is better (compared to the current code, and other alternative changes), and just thoroughly explain the thought process. This makes it much easier to review huge changes, and that in turn makes it much easier to land them.

Once the doc is written, please send an email to the angular mailing list explaining your intent to implement this drastic change, and invite feedback from other developers. If you have results from your use of this change, in terms of performance, and ease of use, be sure to include them in the email as part of your rationale. We don't yet have a template for these launch process emails, but it should be similar to something like the Chromium "intent-to-implement" template (excluding things which don't really apply to angular, such as specifications from the WHATWG or W3C).

After doing that and getting the discussion going, we can figure out a way to move this forward, or kill it, depending on what is deemed best for the project.

@caitp caitp closed this Jan 6, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment