Search code examples
angularjsamazon-s3ng-file-upload

Set $http timeout on the fly


I have an Angular project that has a very nice Timeout toaster that pops up if requests are too slow. But the problem is I need much longer timeouts or timeout resets during a File upload (im using ng-file-upload to s3 storage).

My question is: How could I reset a $http timeout during each progress responses or change it to some massive number only during file-uploads:

Here is my interceptor code in my config function:

$httpProvider.interceptors.push(function ($rootScope, $q, toaster) {
        return {
            request: function (config) {
                //config.cache = true;
                config.timeout = 6000;
                return config;
            },
            responseError: function (rejection) {
                //console.log(rejection);
                switch (rejection.status) {
                    case -1 :
                        console.log('connection timed out!');
                        toaster.pop({
                            type: 'error',
                            title: 'Server Timed Out!',
                            body: 'Waiting for request timed out! \n Please check your Internet connection and try again!',
                            timeout: 6000
                        });
                        break;
                    case 404 :
                        console.log('Error 404 - not found!');
                        toaster.pop({
                            type: 'error',
                            title: 'Server Timed Out!',
                            body: 'Error 404! \n Server returned: Not found! Please check your Internet connection and try again!',
                            timeout: 6000
                        });
                        break;
                }
                return $q.reject(rejection);
            }
        }
    })

Here is my Upload function:

$scope.upload = function (file) {

                                    $scope.count += 1;
                                    file.id= $scope.count;
                                    var durl = apiserv + "api.upload-s3.php?path=" + $scope.folder;
                                    var arr = [];
                                    arr.filename = file.name;
                                    arr.status = "";
                                    arr.progress = 0;
                                    arr.class = "list-group-item-warning";
                                    $scope.files[file.id] = arr;
                                    $http({url: durl}).then(function (drs) {
                                        console.log(drs);
                                        drs.data.file = file;
                                        Upload.upload({
                                            url: drs.data.action, //S3 upload url including bucket name
                                            method: 'POST',
                                            data: {
                                                key: drs.data.key,
                                                acl: drs.data.acl,
                                                Policy: drs.data.Policy,
                                                'X-Amz-Algorithm' : drs.data['X-Amz-Algorithm'],
                                                'X-Amz-Credential' : drs.data['X-Amz-Credential'],
                                                'X-Amz-Date' : drs.data['X-Amz-Date'],
                                                'X-Amz-Signature' : drs.data['X-Amz-Signature'],
                                                //'Content-Type': file.type !== '' ? file.type : 'application/octet-stream',
                                                file: file
                                            }
                                        }).then(function (resp) {
                                            console.log('Success ' + resp.config.data.file.name + 'uploaded. Response: ' + resp.data);
                                            $scope.files[resp.config.data.file.id].status = "Success";
                                            $scope.files[resp.config.data.file.id].progress = 100;
                                            $scope.files[resp.config.data.file.id].class = "list-group-item-success";
                                        }, function (resp) {
                                            console.log('Error status: ' + resp.status);
                                            $scope.files[resp.config.data.file.id].status = "Error: "+ resp.status;
                                            $scope.files[resp.config.data.file.id].progress = 0;
                                            $scope.files[resp.config.data.file.id].class = "list-group-item-danger";
                                        }, function (evt) {
                                            var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
                                            //console.log('progress: ' + progressPercentage + '% ' + evt.config.data.file.name);
                                            console.log(evt.config.data.file);
                                            $scope.files[evt.config.data.file.id].status = "Uploading...";
                                            $scope.files[evt.config.data.file.id].progress = progressPercentage;
                                            $scope.files[resp.config.data.file.id].class = "list-group-item-warning";
                                        });
                                    });
                                };

Solution

  • $http's timeout option accepts promises:

    timeout – {number|Promise} – timeout in milliseconds, or promise that should abort the request when resolved.

    This means that it can be a promise that polls global variable

    config.timeout = $q(function (resolve) {
      var i = 0;
      var interval = setInterval(function () {
        i++;
        if (i * 1000 >= $rootScope.httpTimeout) {
          resolve();
          $rootScope.$apply();
          clearInterval(interval);
        });
      }, 1000);
    });
    

    or implements any other logic that fits the case.