Coder Social home page Coder Social logo

Comments (25)

laurelnaiad avatar laurelnaiad commented on June 1, 2024

This isn't really related to couch potato.

If you are responding to non-Angular events and you want Angular to know about it (usually you do), then wrap your event handler code in $rootScope.$apply(function () { /* your code here */ });

Couch potato, like the rest of the angular components in your app, will then be "in the loop" as to what happens in your event handler.

I'll close this since it isn't really a couch potato issue. If you feel like there is a couch potato aspect to this that I'm missing, please feel free to respond.

EDIT: I should have been a bit more thorough -- if the event you're talking about takes place within the context of a specific view, you can use the $scope associated with that view rather than $rootScope.... basically the gist of it is that whatever scope should be applicable to the event is the one that should know about it. $rootScope if its a global-scoped event, and the $scope of the view if the component is some UI widget in a particular view...

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

I'm not sure I understand. BTW, this isn't really an issue, just a question. In your examples you have a bunch of states, which have resolve: {dummy:blahblah}. I don't want the state to resolve until after the vendor library has run it's script loading (at which time the 'mp_ready' event is fired). Wouldn't this go inside the resolve:{}?

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

Ah, ok. Still not technically a couch potato issue, but at least now I understand your question a bit better.

It seems you'd want the function that you give to the resolve property to return a promise that is resolved by the event handler for the event you specified above. This means that you set up the promise, you return it, and then you hang on to the deferred object so that the event handler can call deferred.resolve().

Because the promise will be hanging unresolved until the event occurs, the resolution process will pause while it waits for that event. Once the event fires, the handler should call resolve on the deferred object, thus resolving the promise, and things move forward.

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

That's exactly right. Before I switched from routes to states, I had the following, in my route config:

resolve: {
                    load: ['$q', '$rootScope', function ($q, $rootScope) {
                        var deferred = $q.defer();
                        require([
                                'someFile',
                                'anotherFile',
                                ], function () {
                            $rootScope.$apply(function () {
                                deferred.resolve();
                            });
                        });
                        return deferred.promise;
                    }]
                }

Is there an example of how I could accomplish this same thing using ui-router and couch potato?

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

BTW, I realize that this isn't a couch potato question, but more of a ui-router/angular question. I apologize for that.

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

I think you may want to use two resolve properties -- one that deals with loading the components you need via couch potato, and another that handles the promise related to the event you're trying to wait for...

Alternatively, if one of the couch potato components you're waiting for depends on the external event happening before it can be considered initialized, then you'd probably shift the burden of listening for the event into the defining module itself (i.e. the require.js module that defines the couch potato component which depends on the event from the external lib).

EDIT: there might be an issue with that alternative, in that require.js doesn't want to wait for promises and wouldn't hold up for an external event either.... so probably the former idea is better than the latter.

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

If you want to combine waiting for your components with waiting for the external event into one resolve function, it might look something like:

resolve: {
  load: ['$q', '$rootScope', function ($q, $rootScope) {
    var overallDeferred = $q.defer();
    var eventDeferred = $q.defer();
    var requireDeferred = $q.defer();

    $q.all([eventDeferred.promise, requireDeferred.promise])
        .then(overallDeferred.resolve);

    require([
    'someFile',
    'anotherFile',
    ], function () {
      $rootScope.$apply(requireDeferred.resolve);
    });

    document.on('mp_ready', function () {
      $rootScope.$apply(eventDeferred.resolve);
    });

    return overallDeferred.promise;
  }]
}

Note: edited since first posted to reflect that it's the promises that are passed to $q.all, not the deferred objects.

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

Great, thanks for that. That might work in ngRoute but I'm using ui.router/scs.couch-potato and resolveDependencies(). Would it work the same way?

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

That might look something like:

resolve: {
  load: ['$q', '$rootScope', '$couchPotato', function (
    $q, $rootScope, $couchPotato
  ) {
    var overallDeferred = $q.defer();
    var eventDeferred = $q.defer();
    var requireDeferred = $q.defer();

    $q.all([eventDeferred.promise, requireDeferred.promise])
        .then(overallDeferred.resolve);

    $couchPotato.resolveDependencies(['someFile', 'anotherFile'])
        .then(requireDeferred.resolve);

    document.on('mp_ready', function () {
      $rootScope.$apply(eventDeferred.resolve);
    });

    return overallDeferred.promise;
  }]
}

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

It's weird, I'm tweaking what you have above, but resolveDependencies() never gets called on couch potato.. I'm trying to figure out why.

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

Ok, resolveDependencies() does get called, however, the requireDeferred never gets resolved, and I can't log anything after that..

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

You can put a breakpoint in your browser around here: https://github.com/stu-salsbury/angular-couch-potato/blob/master/src/couchPotato.js#L166 to figure out what's happening. If it's being called but it's not resolving its promise then something may be erroring out. In looking at the code, I can see that it probably should have a try/catch in it that rejects the promise on catch. Since it's not there, you may find that an error is happening, causing the promise to just die on the vine.

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

If an error is your problem, you could at least get better notification if you change the couch potato function to look like this (untested):

function resolveDependencies(dependencies, returnIndex, returnSubId) {
  function delay($q, $rootScope) {

    var defer = $q.defer();

    try {
      require(dependencies, function() {
        var args = Array.prototype.slice(arguments);

        var out;

        if (returnIndex === undefined) {
          out = arguments[arguments.length - 1];
        }
        else {
          argForOut = arguments[returnIndex];
          if (returnSubId === undefined) {
            out = argForOut;
          }
          else {
            out = argForOut[returnSubId];
          }
        }

        defer.resolve(out);
        $rootScope.$apply();
      });
    }
    catch (err) {
      defer.reject(err);
    }

    return defer.promise;
  }

  delay.$inject = ['$q', '$rootScope'];
  return delay;

}

.... I'd deal with this myself, but I'm kinda busy ATM...

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

I think we're back in couch potato territory, so I'm reopening.... :)

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

It's funny, I tried that before your post. I put one at 165 and 162 and neither of them are being hit. I will keep digging.

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

If they aren't being hit, but resolveDependencies is being hit, then there must be an issue with calling it from the service $couchPotato as opposed to the provider $couchPotatoProvider.

If you're working from the sample code, you probably already injected $couchPotatoProvider at the same time you injected $stateProvider, so it should be available through closure.... this isn't necessarily a kosher way to go, but given what seems like a couch potato bug I'd recommend it for now (adapt as needed):

resolve: {
  load: ['$q', '$rootScope', function (
    $q, $rootScope
  ) {
    var overallDeferred = $q.defer();
    var eventDeferred = $q.defer();
    var requireDeferred = $q.defer();

    $q.all([eventDeferred.promise, requireDeferred.promise])
        .then(overallDeferred.resolve);

    // $couchPotatoProvider is still available due to JS closure from above
    $couchPotatoProvider.resolveDependencies(['someFile', 'anotherFile'])
        .then(requireDeferred.resolve);

    document.on('mp_ready', function () {
      $rootScope.$apply(eventDeferred.resolve);
    });

    return overallDeferred.promise;
  }]
}

Does that help?

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

A note, if I remove '.then(requireDeferred.resolve);' after resolveDependencies(), any code after that line executes. If I leave it in there, nothing executes after it. Might be interesting.

Also, breakpoint at 190 DOES get hit, but breakpoints at 162 and 165 do not get hit.

I will experiment with your previous comment. Thanks!

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

btw, when I say "not kosher" I mean that I lose style points for making this the only way to use the resolveDependencies function, not that your code suffers. The same code is doing the registering one way or the other, I just shouldn't be forcing you to use closure to maintain a reference to the provider.

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

Hmmmm....

if I remove '.then(requireDeferred.resolve);' after resolveDependencies(), any code after that line executes. If I leave it in there, nothing executes after it.

makes me wonder if you're resolve function is the one throwing an unhandled error. You might also want a try/catch of your own...

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

Haha.. It's been a while since I looked at this code. I notice that there is an inner function that is returned by resolveDependencies (named internally as "delay").... which is all well and good when you're setting up your resolve property at config time (as is the case in the sample) since what's left after calling it is a function that itself does the run-time work.

Not so good if all of your code is running at Angular run time. Forget the stuff about switching between the provider and the service.... try this (call the function returned by resolveDependencies):

resolve: {
  load: ['$q', '$rootScope', '$couchPotato', function (
    $q, $rootScope, $couchPotato
  ) {
    var overallDeferred = $q.defer();
    var eventDeferred = $q.defer();
    var requireDeferred = $q.defer();

    $q.all([eventDeferred.promise, requireDeferred.promise])
        .then(overallDeferred.resolve);

    var resolveFunc = $couchPotato.resolveDependencies(['someFile', 'anotherFile']);
    resolveFunc().then(requireDeferred.resolve);

    document.on('mp_ready', function () {
      $rootScope.$apply(eventDeferred.resolve);
    });

    return overallDeferred.promise;
  }]
}

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

(the bug is that if called at run-time, the inner function should be executed right away without you having to do it -- the workaround above should get you past that for now)

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

Ahh, I see what you mean. The problem with that, is now $q and $rootScope are undefined in delay()

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

(Coincidentally or not) I think you happen to have them already! :)

How about:

resolve: {
  load: ['$q', '$rootScope', '$couchPotato', function (
    $q, $rootScope, $couchPotato
  ) {
    var overallDeferred = $q.defer();
    var eventDeferred = $q.defer();
    var requireDeferred = $q.defer();

    $q.all([eventDeferred.promise, requireDeferred.promise])
        .then(overallDeferred.resolve);

   var resolveFunc = $couchPotato.resolveDependencies(['someFile', 'anotherFile']);
   resolveFunc($q, $rootScope)
        .then(requireDeferred.resolve);

    document.on('mp_ready', function () {
      $rootScope.$apply(eventDeferred.resolve);
    });

    return overallDeferred.promise;
  }]
}

from angular-couch-potato.

mparisi76 avatar mparisi76 commented on June 1, 2024

YES!! You rock! Finally got this to work, I tweaked your solution just a hair, using $q.all(), do you see any issues in doing so?

resolve: {
            load: ['$q', '$rootScope', '$document', '$couchPotato', function ($q, $rootScope, $document, $couchPotato) {
              var eventDeferred = $q.defer();
              var requireDeferred = $q.defer();

              var promises = [requireDeferred.promise, eventDeferred.promise];

              var resolveFunc = $couchPotato.resolveDependencies([
                'someFile',
                'anotherFile'
                ]);
                resolveFunc($q, $rootScope).then(requireDeferred.resolve);

              $document.on('mp_ready', function () {
                $rootScope.$apply(eventDeferred.resolve);
              });

              return $q.all(promises);
            }]
          },

from angular-couch-potato.

laurelnaiad avatar laurelnaiad commented on June 1, 2024

Nope: 6 of one, half-dozen of the other. $q.all returns the promise you care about so that should work. Yours is cleaner. 👍

from angular-couch-potato.

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.