调用递归时无法访问成功函数 ajax

Cant access success function when call recursive ajax

我正在构建一个具有推送通知功能的系统并使用 Jersey 创建 API。
我阅读了一篇关于彗星方法的 article,最后得到以下代码:

Index.js

function checkExamNotification() {
    $.ajax({
        url: contextPath + '/api/notification/checkExamNotification',
        type: 'get',
        data: {
            accountId: accountId,
            sessionId: sessionId
        },
        success: function (res) {
            console.log("success");
            displayNumberOfNotification();
            checkExamNotification();
        },
        error: function (jqXHR, textStatus, errorThrown) {
            if (textStatus === "timeout") {
                checkExamNotification();
            }
        }
    });
}

$(document).ready(function () {
    $.ajaxSetup({
        timeout: 1000*60*3
    });
    checkExamNotification();
});

查看考试通知API

@GET
@Path("/checkExamNotification")
public Response checkExamNotification(@QueryParam("accountId") int accountId, @QueryParam("sessionId") String sessionId) throws InterruptedException {
    if (memCachedClient.checkSession(sessionId, accountId)) {
        while (!examNotificationQueue.hasItems()) {
            Thread.sleep(5000);
        }

        ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
        if (examNotificationQueueItemModel.getAccountId() == accountId) {
            LOGGER.info("[START] Check exam notification API");
            LOGGER.info("Account ID: " + accountId);
            LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamId());

            ExamEntity exam = examDAO.findById(examNotificationQueueItemModel.getExamId());
            NotificationEntity notification = notificationDAO.findByExamId(exam.getExamid());
            notification.setSend(1);
            notificationDAO.getEntityManager().getTransaction().begin();
            notificationDAO.update(notification);
            notificationDAO.getEntityManager().getTransaction().commit();

            LOGGER.info("[END]");
            String result = gson.toJson(examNotificationQueueItemModel);
            return Response.status(200).entity(result).build();
        } else {
            examNotificationQueue.enqueue(examNotificationQueueItemModel);
            Thread.sleep(5000);
            checkExamNotification(accountId, sessionId);
        }

    }
    return Response.status(200).entity(gson.toJson("timeout")).build();
}

根据我的调试,API 确实完成了 return 但成功事件有时没有触发。
是的,有时控制台日志成功但有时不成功。
谁能给我解释一下这个案例?
提前致谢。任何帮助将不胜感激。

关注@peeskillet 评论后确定。这是我的最终代码。

查看考试通知API

@GET
@Produces(SseFeature.SERVER_SENT_EVENTS)
@Path("/checkExamNotification")
public EventOutput checkExamNotification(@QueryParam("accountId") final int accountId, @QueryParam("sessionId") final String sessionId) {
    final EventOutput eventOutput = new EventOutput();
    if (memCachedClient.checkSession(sessionId, accountId)) {
        new Thread(new Runnable() {
            public void run() {
                try {
                    if (examNotificationQueue.hasItems()) {
                        ExamNotificationQueueItemModel examNotificationQueueItemModel = examNotificationQueue.dequeue();
                        if (examNotificationQueueItemModel.getAccountId() == accountId) {
                            LOGGER.info("[START] Check exam notification API");
                            LOGGER.info("Account ID: " + accountId);
                            LOGGER.info("Get notification with exam ID: " + examNotificationQueueItemModel.getExamName());
                            String result = gson.toJson(examNotificationQueueItemModel);
                            final OutboundEvent.Builder eventBuilder
                                    = new OutboundEvent.Builder();
                            eventBuilder.data(result);
                            final OutboundEvent event = eventBuilder.build();
                            eventOutput.write(event);
                            LOGGER.info("[END]");
                        } else {
                            examNotificationQueue.enqueue(examNotificationQueueItemModel);
                        }
                    }

                } catch (IOException e) {
                    throw new RuntimeException(
                            "Error when writing the event.", e);
                } finally {
                    try {
                        eventOutput.close();
                    } catch (IOException ioClose) {
                        throw new RuntimeException(
                                "Error when closing the event output.", ioClose);
                    }
                }
            }
        }).start();
    }

    return eventOutput;
}

Index.js

function checkExamNotification() {
    var url = contextPath + '/api/notification/checkExamNotification?accountId=' + accountId + '&sessionId=' + sessionId;
    var source = new EventSource(url);
    source.onmessage = function (event) {
        displayNumberOfNotification();
    };
}