简体   繁体   中英

Handling offline data in a Ionic App using an interceptor

So a little bit of a background, I have this project and am working on Version 2 which involves adding in offline functionality. I am stuck to the following stack as changing it now would involve to much overhead:

Laravel API MYSQL Ionic

I have heard a lot about syncing using Pouch/CouchDB but unfortunately I can't change everything to use this stack.

I decided in my limited AngularJS/JS knowledge to use a HTTP Interceptor to intercept all requests, check if it is a POST/PUT request, check if the device is on/offline and either save the data in local storage or carry on with the request. This is where the issues begin.

Here is my APIInterceptor:

App.factory('APIInterceptor', function ($q) {

    return {
        request: function (config) {

            if(config.method == 'POST' || config.method == 'PUT')
            {
                //Add data to localstorage

                //Exit without actually sending the request to the server.
                return $q.reject();
            }

            return config || $q.when(config);
        }
    };
});

As you can see I am returning .reject() but what I need is mimic the API response and pass back to my service as if the request was processed successfully so my app can carry on as normal. Essentially returning success, status code 200 after the data was stored in localstorage.

Any suggestions on how I can do this?

Wouldn't that be easier to create a service where you manage all the http requests and, eventually, return your database data?

Interceptors

For purposes of global error handling, authentication, or any kind of synchronous or asynchronous pre-processing of request or postprocessing of responses, it is desirable to be able to intercept requests before they are handed to the server and responses before they are handed over to the application code that initiated these requests. The interceptors leverage the promise APIs to fulfill this need for both synchronous and asynchronous pre-processing.

I guess you don't need to check if the device is online/offline as you would get a requestError in your interceptor.

Since you want to intercept the communication before it actually happens you can use this sort of interceptor:

.factory('APIInterceptor', function APIInterceptor($q) {
    return {
            request: function (config) {
                if(config.method == 'POST' || config.method == 'PUT')
                {
                    return $q.reject({status: 503, config: config});
                }
                return config || $q.when(config);
            },

            // response: function (httpResponse)
            // {
            //     return httpResponse || $q.when(httpResponse);
            // },

            responseError: function (rejection)
            {
                if (rejection.status === 503) {
                    rejection.status = 200;
                    rejection.statusText = "OK";
                    rejection.data = {};
                    return $q.resolve(rejection);
                }
                return $q.reject(rejection);
            }
        };
});

If the request is POST or PUT you can reject it adding a status and passing the configuration as well:

if(config.method == 'POST' || config.method == 'PUT')
{
    return $q.reject({status: 503, config: config});
}

responseError will be processed.
Now you can check your status and resolve the promise so that your $http call does not catch an exception:

if (rejection.status === 503) {
    rejection.status = 200;
    rejection.statusText = "OK";
    rejection.data = {};
    return $q.resolve(rejection);
}

I've appended a data object cause that's what your http call might expect. Basically, what we're doing here is trying to recreate a proper response.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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