chrisben / imgcache.js

JS library based on the File API to cache images for offline recovery (target: cordova/phonegap & chrome)
Other
825 stars 214 forks source link

ImgCache.js init only fires after several calls #87

Open msandt3 opened 9 years ago

msandt3 commented 9 years ago

For a little background I'm working on the project referenced in Issue 70.

I've moved away from actually initializing the ImgCache plugin using a deviceready event, but rather initializing on ionic's $ionicPlatform.ready. This essentially does the same thing. Waits til all of the plugins are loaded etc before running any code. See angular-imgcache.js for more details.

Using this method I have been able to successfully initialize ImgCache but not consistently. As sometimes it seems the callback will fire before the file plugin and hooks are actually loaded. Obviously this is an ionic issue, but I just wanted to provide a bit of background.

In a bit of an experiment, I wrapped ImgCache in an angular service to provide initialization capabilities. I've injected this service in several controllers and called the init function. Running with the phonegap app on an android device (v 4.4) there are cases where the init call is fired successfully on the first try. Other times I have to access the controller 2 or 3 times before I see the confirmation that ImgCache has been initialized successfully. Is this a known issue or something you've encountered during debugging? It seems as if it is behaving correctly but not consistently which is something confounding.

For reference I'll include some sample code so you can understand what's going on.

Image Cache Angular Service

.factory('ImgCacheService',[
    '$q',
    '$window', 
    function ($q, $window) {
        return {
            initialize: function() {
                var deferred = $q.defer();
                $window.ImgCache.options.debug = true;
                $window.ImgCache.options.chromeQuota = 50*1024*1024; 
                $window.ImgCache.init(function() {
                    deferred.resolve();
                }, function(){
                    deferred.reject();
                });
                return deferred.promise;
            }
        }   
    }]);

Controller

.controller('LoginController', ['$scope','$timeout','$ionicLoading','$ionicPopup','$location','$state','User','persistencejs','SyncHandler','ImgCacheService',
    function ($scope, $timeout, $ionicLoading, $ionicPopup, $location, $state, User, persistencejs, SyncHandler,ImgCacheService){
        ImgCacheService.initialize().then(function(){
            console.log('ImgCacheInitialized!');
        }, function() {
            console.log('ImgCacheFailed');
        });
        $scope.login = function() {
            User.login().then(function(){
                $state.go('menu.tours');
            });
        };
}])

The strangest thing is it functions as expected when developing via a web browser but not via the phonegap developer app or phonegap build.

chrisben commented 9 years ago

Hi @msandt3 ,

I didn't know about that angular wrapper, thanks for the link I will check it out.

The init method is mostly just creating the cache folder using the file plugin. If that plugin is not ready yet, the asynchronous method creating the folder might never reach the callback, that's perhaps what you're experiencing. Try to turn debug on (ImgCache.options.debug = true;) to try to see where it stops working.

Perhaps you would like to know that I've started a wrapper for ImgCache that implements the Promises interface, that could perhaps ease your work there. It will call the init method whenever needed so you don't have to care too much about it. It's in the Promises branch for now.

I hope that helped.

ssandison commented 9 years ago

I think I am now encountering this issue or similar. I am using appgyver which is based on cordova. The ImgCache.init() function gets executed successfully but the success callback seems to only be able to execute alert() calls. I need it to run angular.bootstrap() but it will only execute alerts(), it won't execute console.log() either. I would like to use promises if possible but I am using ImgCache.useCachedBackground() which hasn't been implemented yet. Will promises solve this problem?

chrisben commented 9 years ago

javascript code doesn't randomly skip instructions. I suppose your javascript environment doesn't implement "console", see this stackoverflow, or rather its output is not given to you. You can now overload the log function using the options, I've seen you have a steroids.logger.log method for appgyver that might output something you can actually see in your logs. Here's the documentation I found from appgyver.

Promises shouldn't help you much there, it's only a wrapper that calls the init method.

ssandison commented 9 years ago

I know it doesn't make sense. I think it is something to do with window.requestFileSystem sometimes failing to execute the success callback.

I have found a workaround for the problem however. AppGyver implements two different WebViews for android. I was using the chromium engine that was failing to correctly execute success callbacks but by switching to the native platform WebView of the device I am now getting consistent callbacks. I also had a separate issue where cdvfile:// isn't working for showing cached images. I worked around this by using base64 encoded option (useDataURI). Thanks again for your excellent script.

chrisben commented 9 years ago

@msandt3 does the feedback from @ssandison helps you there?