Как прервать предыдущую отправку запроса в angluarjs (MEAN application)?

#javascript #angularjs #node.js #express

#javascript #angularjs #node.js #выразить

Вопрос:

Я разрабатываю приложение MEAN Stack.В приложении, если я нажимаю на ссылку несколько раз, она отправляет на сервер несколько раз, это приводит к зависанию браузера, отказу отвечать на запросы или сбою.

Ниже приведен фрагмент кода, в котором я извлекаю фотографии с сервера.Он поступает с сервера, но когда я нажимаю на ссылки 3-4 раза, ответ может задержаться или зависнуть в браузере.В этой ситуации мне потребовалось прервать предыдущие запросы и выполнить только текущий запрос.

Как мне предотвратить отправку нескольких запросов или, если приложение позволяет отправлять несколько запросов, то как прервать предыдущую отправку запроса? Можете ли вы дать мне правильное решение и управление кодом?

PhotoController.js

     (function () {

        'use strict';
        /**
         * Photo Controller for photo features
         * @param {type} $rootScope
         * @param {type} $scope
         * @param {type} $state
         * @param {type} $timeout
         * @param {type} HzServices
         * @param {type} HzPhotoService
         * @param {type} Upload * @returns {undefined}
         */
        function PhotoCtrl($rootScope, $scope, $state, $window, $routeParams, $timeout, HzServices, HzPhotoService, Upload, HzSocket, notifications) {
            /*
             * Initiliaze custom scrollbar for following features
             * rightside - my album list
             * add/edit album - emoji list
             */
            //Data loads when $viewContentLoaded.
            $scope.$on('$viewContentLoaded', function () {
                $scope.counter = 0;
                $scope.currentTab = 'all-photos';
                $scope.init();
                $scope.doAlbumList('', '', '', '', 0, 0);
            });

            // Scroll to top, when page loads
            angular.element("html, body").animate({
                scrollTop: 0
            }, 0);


            /*
             *Initialize select2 options for email ids
             */
            $scope.init = function () {
                $scope.select2Options = {
                    multiple: true,
                    'simple_tags': true,
                    tokenSeparators: [','],
                    tags: [], // Can be empty list.
                    selectOnBlur: true,
                    formatNoMatches: function () {
                        return '';
                    },
                    dropdownCss: {display: 'none'}
                };
                $scope.myAlbumListConfig = HzServices.initNgScrollbarsConfig();
                $scope.myAlbumEmojiConfig = HzServices.initNgScrollbarsConfig();
                $scope.frmPhoto = null;
                $rootScope.photoIndex = 0;
                // Prevent to sent request to server by continuously click on "All photos"
                $scope.defaultAlbum = null;
                $scope.fullWidthClass = null;
                $scope.albums = {};
                $scope.albumsCount = null;
                $scope.myAlbums = {};
                $scope.myAlbumsCount = null;
                $scope.photos = {};
                $scope.photosByDate = {};
                $scope.photosCount = null;
                //set model variable for photo pagination
                $scope.photoRecordsOffset = 0;
                $scope.photoRecordsTotal = 0;
                $scope.photoYears = [];
                $scope.albumModel = {album_name: "", album_description: "", album_emoji: "", is_auto_generate: 0};
                $scope.myAlbumIsAutoGenerated = 1;
                $scope.photoModel = {};
                $scope.browsePhotoModel = {};
                // Set default global variables of edit album
                $scope.deletedPhotoTotal = 0;
                $scope.deleteFlag = false;
                $rootScope.emojis = {};
                $scope.arrPhoto = [];
                $scope.modelChkBrowsePhoto = {};
                $scope.selectedBrowsePhotoIden = [];
                $scope.selectedBrowsePhotoIndex = [];
                $scope.deSelectedBrowsePhotoIden = [];
                $scope.obsoleteBrowsePhotoIden = [];
                $scope.checkAllFlag = false;
                $scope.overBox = {};
                $scope.deleteBox = {};
                $scope.moveBox = {};
                $scope.overBoxFlag = false;
                $scope.deleteBoxFlag = false;
                $scope.moveBoxFlag = false;
                $scope.currentSelectedPhotoCount = 0;
                $scope.currentMovedPhotoCount = 0;
                $scope.currentDeletedPhotoCount = 0;
                $scope.filesLen = 0;
                $scope.counter = 0;
            };

            /**
             * Lists available albums of user
             * @param {String} pagination
             * @param {String} album
             * @param {Number} recordsPerPage
             * @param {String} selectedTab
             * @param {Boolean} includeMovedPhotos
             * @returns {undefined}
             */
            $scope.doAlbumList = function (pagination, album, recordsPerPage, selectedTab, includeMovedPhotos, includeDeletedPhotos) {
                HzServices.showActiveElementTab();
                angular.element("ul.error-log li").remove();

                //$rootScope.arrData = [];

                /*
                 * Pagination params
                 */
                if (!!pagination amp;amp; pagination === "VIEWMORE") {
                    $scope.photoRecordsOffset = $scope.photoRecordsOffset   $rootScope.recordsPerPage;
                }

                /*
                 * Following condition is affected specficially when move photo to album and it requires
                 * to display and update photos for those particular photos. There is not requires to update
                 * other photos of an album
                 * When $scope.arrPhoto is blank so it consider, default behaviour of listing, otherwise it lists only
                 * those photos which are listed in edit photos option.
                 */
                var data = {};
                if ($scope.arrPhoto.length === 0) {
                    data = {
                        q: $state.params.pid, // Userid
                        album: album, // album Id
                        // custom records offset used in move album section and update pagination used both recordsPerPage and recordsOffset
                        // records per page
                        recordsPerPage: (!!recordsPerPage) ? recordsPerPage : $rootScope.recordsPerPage,
                        recordsOffset: $scope.photoRecordsOffset,
                        // It includes photos which are moved from source album to destination album but source album reference is also present,
                        // It helps to know which photo is moved from current album to destination album in move album tab.
                        includeMovedPhotos: includeMovedPhotos,
                        includeDeletedPhotos: includeDeletedPhotos
                    };
                } else {
                    data = {
                        pid: $scope.arrPhoto
                    };
                }
                /*
                 * Pagination
                 */
                var deferred = HzServices.deferred("/api/album/list", 'POST', data);
                deferred.then(
                        function (res) {
                            /*
                             * success in repsonse
                             * Share common photo amp; album data across all controllers, directives by angular custom service.
                             */
                            var data = {album: {count: res.data.count.album, data: res.data.album}, albumWithDeletedPhoto: {count: res.data.count.albumWithDeletedPhoto, data: res.data.albumWithDeletedPhoto}, myAlbum: {count: res.data.count.myAlbum, data: res.data.myAlbum}, myAlbumWithDeletedPhoto: {count: res.data.count.myAlbumWithDeletedPhoto, data: res.data.myAlbumWithDeletedPhoto}, photo: {count: res.data.count.photo, data: res.data.photo}};
                            HzPhotoService.setSharedData(data);
                            if (false === !!$scope.myAlbumName amp;amp; false === !!$scope.myAlbumId) {
                                $scope.myAlbumName = "All photos";
                                $scope.myAlbumId = "";
                            }
                            //Create an array of magnific inline popup content
                            //HzPhotoService.setInlinePopupContent(data.photo.data);
                            var sharedData = HzPhotoService.getSharedData();
                            //Get all albums list
                            $scope.albums = sharedData.album.data;
                            $scope.albumsCount = sharedData.album.count;
                            //Get all albums with deleted records list
                            $scope.albumsWithDeletedPhoto = sharedData.albumWithDeletedPhoto.data;
                            $scope.albumsWithDeletedPhotoCount = sharedData.albumWithDeletedPhoto.count;
                            //Get my custom albums list
                            $scope.myAlbums = sharedData.myAlbum.data;
                            $scope.myAlbumsCount = sharedData.myAlbum.count;
                            //Get my custom album with deleted records list
                            $scope.myAlbumWithDeletedPhoto = sharedData.myAlbumWithDeletedPhoto.data;
                            $scope.myAlbumWithDeletedPhotoCount = sharedData.myAlbumWithDeletedPhoto.count;

                            // Pagination if required
                            if (pagination === "VIEWMORE") {
                                $scope.photos = $scope.photos.concat(sharedData.photo.data);
                            } else {
                                if ($rootScope.recordsOffset === 0) {
                                    $scope.photos = sharedData.photo.data;
                                }
                            }
                            $scope.photosByDate = HzPhotoService.setSharedDataByDate((pagination === "VIEWMORE") ? true : false);
                            //BrowsePhotoModel to pass all photos lists to directive
                            $scope.browsePhotoModel = $scope.photos;
                            //$scope.uploadResults = $scope.photos;
                            $scope.photosCount = sharedData.photo.count;
                            $scope.photoRecordsTotal = $scope.photosCount;
                            if (selectedTab === "edit_album") {
                                $scope.doToggleSelectAll($scope.checkAllFlag, $scope.photoRecordsOffset);
                            }

                            // Get Emoji list
                            // if (!!HzPhotoService.getSharedEmojis()) {
                            if (0 === Object.keys($rootScope.emojis).length) {
                                $scope.doEmojiList();
                            }
                        },
                        function (res) {
                            /*
                             * Error hading in repsonse
                             */
                            var data = {album: {count: $scope.albumsCount, data: $scope.albums}, albumsWithDeletedPhoto: {count: $scope.albumsWithDeletedPhotoCount, data: $scope.albumsWithDeletedPhoto}, myAlbum: {count: $scope.myAlbumsCount, data: $scope.myAlbums}, myAlbumWithDeletedPhoto: {count: $scope.myAlbumWithDeletedPhotoCount, data: $scope.myAlbumWithDeletedPhoto}, photo: {count: $scope.photosCount, data: $scope.photos}};
                            HzPhotoService.setSharedData(data);
                            notifications.showSuccess({
                                message: "Oops! something went wrong, please try again later.",
                                hideDelay: 3000, //miliseconds
                                hide: true // boolean
                            });
                        })
                        .catch(function (response) {
                            console.error('request error', response.status, response.data);
                        })
                        .finally(function () {
                            console.log("finally finished request");
                        });
            };
            /**
             * get emoji list
             * @returns {undefined}
             */
            $scope.doEmojiList = function () {
                var deferred = HzServices.deferred("/api/emoji/getlist", 'GET');
                deferred.then(
                        function (res) {
                            HzPhotoService.setSharedEmojis(res.data);
                            // console.log($rootScope.emojis);
                            $scope.isEmojiVisible = false;
                        },
                        function (err) {
                            notifications.showSuccess({
                                message: "Oops! something went wrong, please try again later.",
                                hideDelay: 3000, //miliseconds
                                hide: true // boolean
                            });
                        }
                );
            };
        }

        angular
                .module("AppDream")
                .controller('PhotoCtrl', ['$rootScope', '$scope', '$state', '$window', '$routeParams', '$timeout', 'HzServices', 'HzPhotoService', 'Upload', 'HzSocket', 'notifications', PhotoCtrl]);
    }());
  

HzServices.js

     (function () {
        'use strict';
        angular
                .module("AppDream")
                .factory("HzPhotoService", ['$rootScope', '$state', 'HzServices',
                    function ($rootScope, $state, HzServices) {
                        var methods = {};
                        var arrData = [];
                        var sharedData = {};
                        var sharedDataByDate = {data: []};
                        var sharedEmojis = {};
                        $rootScope.emojis = {};
                        var setSharedData = function (data) {
                            sharedData = data;
                        };
                        var getSharedData = function () {
                            return sharedData;
                        };
                        var setSharedEmojis = function (data) {
                            //sharedEmojis = data;
                            $rootScope.emojis = data;
                        };
                        var getSharedEmojis = function () {
                            return $rootScope.emojis;
                            //return sharedEmojis;
                        };
                        var setSharedDataByDate = function (isAllowToConcat, photos) {
                            var sharedDataPhotoLength = (!!photos) ? photos.length : sharedData.photo.data.length;
                            var dateFindIndex = -1, d = null;
                            (isAllowToConcat === false) ? sharedDataByDate.data = [] : "";
                            if (sharedDataPhotoLength > 0) {
                                var photos_ = (!!photos) ? photos : sharedData.photo.data;
                                angular.forEach(photos_, function (value, index) {
                                    d = new Date(value.created_at).toDateString();
                                    dateFindIndex = IsDateExists(d);
                                    if (dateFindIndex === -1) {
                                        var tempObj = {date: d, data: []};
                                        sharedDataByDate.data.push(tempObj);
                                        dateFindIndex = IsDateExists(d);
                                    }
                                    sharedDataByDate.data[dateFindIndex].data.push(value);
                                    //console.log("<br/>Row index : "   index   "<br/>>> data length : "   dataLength   "<br/>>> datefindIndex : "   datefindIndex   "<br/>>> Date to find : "   d);
                                });
                            }
                            return sharedDataByDate;
                        };
                        var getSharedDataByDate = function () {
                            return sharedDataByDate;
                        };
                        var IsDateExists = function (date) {
                            var sharedDataByDateLength = sharedDataByDate.data.length;
                            for (var index = 0; index < sharedDataByDateLength; index  ) {
                                if (date === sharedDataByDate.data[index].date) {
                                    return index;
                                }
                            }
                            return -1;
                        };
                        var setInlinePopupContent = function (data) {
                            /*
                             * Create an array of magnific inline popup content
                             */
                            var index = 0;
                            angular.forEach(data, function (value, key) {
                                if (value.data.length > 0) {
                                    var loopIndex = 0;
                                    angular.forEach(value.data, function (value_, key_) {
                                        arrData.push({
                                            imageDescriptionDiv: ("" === value_.photo_description) ? "Description writes here" : value_.photo_description,
                                            imageDescriptionHidden_value: value_.photo_description,
                                            //imageDescriptionTxtArea: value_.photo_description,
                                            //imageScale_img: "/resize/"   value_.module   "/"   value_.photo_name,
                                            //imageOriginal_href: "/"   value_.module   "/"   value_.photo_name,
                                            imageScale_img: $rootScope.app_dir.resize_730_730   "photo/"   value_.photo_name,
                                            imageOriginal_href: $rootScope.app_dir.web_path   "photo/"   value_.photo_name,
                                            imageIden_value: value_._id,
                                            imageTxtDescription_id: value_._id,
                                            imageIndex_value: index,
                                            imageYear_value: value.year,
                                            imageYearIndex_value: loopIndex
                                        });
                                        loopIndex  ;
                                        index  ;
                                    });
                                }
                            });
                        };
                        var getInlinePopupContent = function () {
                            return arrData;
                        }

                        return {
                            setSharedData: setSharedData,
                            getSharedData: getSharedData,
                            setSharedEmojis: setSharedEmojis,
                            getSharedEmojis: getSharedEmojis,
                            setSharedDataByDate: setSharedDataByDate,
                            getSharedDataByDate: getSharedDataByDate,
                            IsDateExists: IsDateExists,
                            setInlinePopupContent: setInlinePopupContent,
                            getInlinePopupContent: getInlinePopupContent
                        };
                    }
                ]);
    }());
    > HzServices.js

    (function () {
        'use strict';
        angular
                .module("AppDream")
                .factory("HzServices", ['$rootScope', '$http', '$cacheFactory', '$q', '$location', 'notifications',
                    function ($rootScope, $http, $cacheFactory, $q, $location, notifications) {
                        return {
                            /**
                             * Common $q reponse
                             * @param {type} url
                             * @param {type} method
                             * @param {type} data
                             * @returns {object}
                             * @description Common method to get ajax response via $q api
                             */
                            deferred: function (url, method, data) {
                                var req = {
                                    method: method,
                                    url: url,
                                    headers: {
                                        'Content-Type': "application/json"
                                    },
                                    cache: false
                                };
                                if ("GET" === method.toUpperCase()) {
                                    req.params = data;
                                } else if ("POST" === method.toUpperCase()) {
                                    req.data = data;
                                } else {
                                    req.data = "";
                                }

                                var deferred = $q.defer();
                                $http(req)
                                        .success(function (data, status, headers, config) {
                                            deferred.resolve(data);
                                        })
                                        .error(function (data, status) {
                                            deferred.reject(data);
                                        });
                                return deferred.promise;
                            },
                            /**
                             * Return default media folder by photos, videos
                             * @param {String} media
                             * @returns {undefined}
                             */
                            getDefaultMediaFolder: function (media) {
                                switch (media) {
                                    case "photo":
                                        return "wall photos";
                                        break;
                                    case "video":
                                        return "wall photos";
                                        break;
                                }
                            },
                            getAppUrl: function () {
                                switch ($location.host()) {
                                    case "node.dream.com":
                                        return $location.protocol()   "://"   $location.host()   ":3030";
                                        break;
                                    case "staging.dream.com":
                                        return $location.protocol()   "://"   $location.host()   ":3131";
                                        break;
                                    case "dream.com":
                                        return $location.protocol()   "://"   $location.host()   ":1010";
                                        break;
                                    default:
                                        return $location.protocol()   "://"   $location.host()   ":"   $location.port();
                                        break;
                                }
                            }
                        };
                    }
                ]);
    }());
  

Комментарии:

1. К вашему сведению — все это обрабатывается на клиенте, на сервере ничего. Если вы хотите предотвратить отправку нескольких запросов, то проверьте, отправили ли вы уже запрос (и не получили ли от него ответа), прежде чем отправлять другой. Если вы хотите отправить несколько запросов, abort() используйте любой предыдущий активный запрос.

2. @Adam: Я знаю это .. это обрабатывается от клиента, но я не знаю, как на самом деле реализовать в angluarjs.

3. Возможно, вам следует показать нам свой код и то, что вы пробовали

4. хорошо, дайте мне отредактировать и узнать вас.

5. @Adam: пожалуйста, проверьте мой вопрос еще раз.