Skip to content

Instantly share code, notes, and snippets.

@clichedmoog
Created January 26, 2024 15:12
Show Gist options
  • Save clichedmoog/8de4fa860b5ebbdd2a59c5fe7b4558b9 to your computer and use it in GitHub Desktop.
Save clichedmoog/8de4fa860b5ebbdd2a59c5fe7b4558b9 to your computer and use it in GitHub Desktop.
롱 폴링을 이용한 알림 확인 코드 예제
# 로그이 필요 데코레이터
# REST API에 오류철 핸들러 데코레이터
@decorators.ajax_error_response_v2
@decorators.ajax_login_required_v2
def notifications(request):
data = {}
user = request.user
# 파라메터에 따라 몇 가지 동작을 지원함
if request.method == 'GET':
# count 파라메터는 곧바로 뱃지 갯수 가져오기
if 'count' in request.GET:
count = Notification.badge_count(user)
data['count'] = count
# change는 50초 동안 실행하면서 5초에 한번씩 뱃지 숫자가 변경되었나 확인
elif 'change' in request.GET:
count = Notification.badge_count(user)
data['count'] = count
for i in range(10): # run during 50 seconds + excution time
count = Notification.badge_count(user)
if data['count'] != count:
items = []
data['count'] = count
objs = Notification.objects.filter(user_id=user.pk) \
.filter(modified__gte=user.notified)
for obj in objs:
item = obj.v2_to_dict()
items.append(item)
data['items'] = items
break
time.sleep(5)
# 둘다 아닌경우는 알림 내용을 가져옴
else:
items = []
per_page = request.GET.get('n', 99)
page = request.GET.get('p')
objs = Notification.objects.filter(user=user)
# pagination if required
if page:
paginator = Paginator(objs, per_page)
try:
objs = paginator.page(page)
except EmptyPage:
objs = []
for obj in objs:
item = obj.v2_to_dict()
items.append(item)
data['items'] = items
# PUT인 경우 뱃지 갯수 클리어
elif request.method == 'PUT':
user = request.user
Notification.clear_badge(user)
data['count'] = 0
return json_response(request, data)
var do_poll = function(count) {
// AngularJS 1.x에서는 setInterval()에 해당하는 $interval()을 지원핮 않아서 $timeout()사용
$timeout(function() {
// 60초까지 기다림
$scope.polling_promise = ajax('GET', 'user/notifications?change', {}, undefined, 60000)
.success(function(response, status, headers, config) {
// 성공시 뱃시 카운트를 화면ㅇ 표시
if (typeof response['data']['count'] !== 'undefined') {
$scope.notification_count = response['data']['count'];
if ($scope.notification_count > 99) { // Display as '99+' when reached maximum count
$scope.notification_count = '99+';
}
}
if (typeof response['data']['items'] !== 'undefined') {
angular.forEach(response['data']['items'].reverse(), function(item) {
// replace notification if exist or add at first position
if (!search_replace_array($scope.notifications, item, 'id')) {
$scope.notifications.unshift(item);
}
});
}
do_poll();
}).error(function(response, status, headers, config) {
// 오류인 경우 다시 폴링하거나 로그인 하지 않았다면 폴링을 중단
if (status == 403 && response['error'] && response['error']['code'] == 1300) {
$scope.stop_polling();
} else {
do_poll();
}
});
// 다시 폴링을 시작하면 5초 기다리고 나서 시작함
}, 5000);
};
$scope.start_polling = function() {
ajax('GET', 'user/notifications?count', {count: true, poll: 0})
.success(function(response, status, headers, config) {
if (response['data'] && response['data']['count']) {
$scope.notification_count = response['data']['count'];
}
}).error(function(response, status, headers, config) {
}).always(function() {
});
$scope.polling_promise = do_poll();
};
$scope.stop_polling = function() {
if ($scope.polling_promise) {
$timeout.cancel($scope.polling_promise);
}
$scope.polling_promise = null;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment