Giter Club home page Giter Club logo

Comments (5)

anantn avatar anantn commented on May 29, 2024

Hey @amazari, thanks for the excellent analysis!

This issue has been bugging me as well - though I don't think it's an issue that promises can only be resolved once. As you point out, the right approach might be to simply use different variables to store the promise and the value. Why is it a problem that the promise is resolved only once if we simply update the variable automatically later (through $apply)?

from angularfire.

katowulf avatar katowulf commented on May 29, 2024

I've been using Promises with Firebase extensively and effectively. I rely on the progress method for streaming data. Example:

function loadPath( path ) {
     return _.Deferred(function(def) {   //$.Deferred is just as good here
         var ref = new Firebase(path);

         // call the .progress listener any time a child is received
         // the _.defer here is very important, see below
         var fn = ref.on('child_added', _.defer(def.notify));

         // if the deferred is resolved or rejected at any point, then we close the FB listener
         def.always(function() {
               ref.off(fn);
         });
     }, function(error) {  // cancel callback (security errors)
          def.reject(error);
     });
};

loadPath( USER_PATH )
     .progress(function(ss) { console.log('loaded user', ss.name()); })
     .done(function() { console.log('connection cancelled'); })
     .fail(function(e) { console.log('security error', e); });

One caveat to this approach is that data already stored locally is returned synchronously, so you have to be on the lookout for that use case. Example:

function loadDataBadly( path ) {
     return _.Deferred(function(def) {   //$.Deferred is just as good here
         var ref = new Firebase(path);

         // uh oh!
         var fn = ref.on('child_added', def.notify);
     });
};

// this one gets all the records
loadDataBadly(USER_PATH).progress(...);

// this one will be sad because some records are already cached locally
// which means that the notify callback will get fired before the .progress listener is attached : (
loadDataBady(USER_PATH).progress(...);

from angularfire.

amazari avatar amazari commented on May 29, 2024

@anantn : Thanks for your quick feedback !

Why is it a problem that the promise is resolved only once if we simply update the variable automatically later (through $apply)?

In the current state, the promise has no effect anyway. For instance, removing all deferred-related code still works perfectly [0](I also remove all the typecheck code for clarity sake).

The problem arises when you want to edit the data. As stated in the doc, user should do it only when the promise is realized in a 'then' handler to ensure consistency.
This work for initial load, as the promise is realized once and the 'then' callback is fired, but subsequent modifications might happen while loading data as the then block is never called again (not sure I am very clear here :) ).

Ideally I should be able to compose the items promise with another promise (usually an event triggered by the user) to make sure model modification only happens when data is in a stable state:

$scope.items = [];
var clickPromise = clickPromiseFor(button);
var itemsPromise = angularFire(url, $scope, 'items', []);

var clickAndItemsPromise = $q.all ([
                                                                clickPromise,
                                                                itemsPromise
]);

clickAndItemsPromise.then (function (){
   $scope.items.push({...});
});

Somehow, we need to reuse or replace the promise to always get a fresh one. Again, this is contorsionning the Promise/Deffered semantic as they are one-shot stuff. Reactive programming has nice abstractions for value that changes over time.

An advantage of binding to a promise in the template, instead of modifying the value ourself, is to benefit from angular's machinery that finds out the delta between current and new value and only updates the DOM linked to the sub-scope of this diff.

[0] https://gist.github.com/amazari/5418870

from angularfire.

amazari avatar amazari commented on May 29, 2024

@katowulf : sadly Angular's deffered/promises lacks any kind of continuous event like 'progress' :(

from angularfire.

anantn avatar anantn commented on May 29, 2024

The promise is now only used to be notified when the "initial" data loads. Changes made to the local model before the remote data arrives will be merged.

from angularfire.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.