(Неперехваченное обещание) Не удалось получить при POST другой контент json

Я пытаюсь получить списки пользователей GET с сервера node.js с помощью API-интерфейса выборки, используя POST-код json {pageNumber,UsersPerPage}. Для этого у меня есть две кнопки, каждая из которых отправляет на сервер свое собственное текстовое содержимое в виде номеров страниц при нажатии. Однако после шестикратного повторения двух кнопок API выборки почему-то не работает. Это не удается после того, как я отправляю 6 запросов на выборку - поэтому, когда я шесть раз перебираю между двумя кнопками - и появляется сообщение об ошибке «Необнаруженный (в обещании) TypeError: Не удалось получить данные в HTMLDivElement». возвращается.

Это мой код интерфейса:


side1.addEventListener('click',()=>{
    fetch('/api/users/stats/side1/post',{  
       method:'POST',
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side1.textContent,
        userPerPage:userPerSide
       })
    
    });
    fetch('/api/users/stats/side1/get').then(x=>x.text()).then(Txt=>{
    display.innerHTML=Txt;
    });
});
side2.addEventListener('click', ()=>{
    fetch('/api/users/stats/side2/post',{
       method:'POST' ,
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side2.textContent,
        userPerPage:userPerSide
       })
    
    });  
    fetch('/api/users/stats/side2/get').then(x=>x.text()).then(Txt=>{
        display.innerHTML=Txt;
        });  
});


Это мой бэкэнд — код:


var retVal; 
app.post('/api/users/stats/side1/post',(req,res)=>{
if (req.body){
const {pageNum,userPerPage}=req.body;
retVal=GetPage(Number(pageNum),Number(userPerPage));
}
});
app.post('/api/users/stats/side2/post',(req,res)=>{
    if (req.body){
    const {pageNum,userPerPage}=req.body;
    retVal=GetPage(Number(pageNum),Number(userPerPage));
    }
});
app.get('/api/users/stats/side1/get',(req,res)=>{
res.setHeader('content-type', 'text/plain');
res.send(retVal);
});
app.get('/api/users/stats/side2/get',(req,res)=>{
res.setHeader('content-type', 'text/plain');
res.send(retVal);
});


Я пробовал разные флаги заголовков, например явное объявление Access-Control-Allow-Origin или no-cors, а также async, await во внешнем интерфейсе. Ошибка возникает независимо от типа контента, возвращаемого сервером. Я попытался упростить код и изменить URL-адреса POST и GET для разных объектов html, чтобы избежать коллизий. Я ожидал, что запросы на выборку будут выполнены без какой-либо блокировки. Я уже выполнял поиск в Интернете, а также в stackoverflow, и хотя другие вопросы кажутся мне знакомыми, я думаю, они касаются совершенно другой проблемы.

Что я выучил: Проблема не возникает из-за того, что запросы занимают слишком много времени. И это не из-за того, что Javascript не может взаимодействовать с моим сервером, поскольку первые 5 запросов работают как положено, а затем код ломается. Глядя на вкладку сети, запросы внезапно становятся ожидающими, поэтому после этого момента они перестают проходить.

Возможно, проблема в том, что вы не передаете заголовки Content-Type и Content-Length перед вызовом res.send(retVal).

DiD 28.05.2024 15:18

Проблема возникает не здесь, а где-то в логике получения/отправки, я просто не могу понять, где. Однако спасибо за вклад. Возможно, я отредактирую сообщение, чтобы было видно, что проблема не в этом.

Bell Flo 28.05.2024 15:22

Вы проверяли вкладку «Сеть» в инструментах разработчика? Чтобы увидеть, в чем ошибка запроса?

Salketer 28.05.2024 15:32

Что также интересно, так это то, что ему не удалось получить HTMl_Div_Element, это относится к вызову выборки, который отправляет POSTSside1.textContent, но как он вдруг не получает это?? Страница также не может перезагрузиться на этом этапе. Так происходит ли еще какая-то блокировка и как?

Bell Flo 28.05.2024 15:32

Да, я проверил вкладку «Сеть». Что происходит с запросами, так это то, что они находятся на рассмотрении. Итак, они каким-то образом перестают проходить, поэтому, вероятно, происходит какая-то блокировка, но я просто не могу понять, где это будет.

Bell Flo 28.05.2024 15:34

Ну, это очень странный код. Ваше сообщение предварительно заполняет ответ get. Почему POST просто не возвращает ответ? Вам не придется делать два звонка. Кроме того, ваша выборка GET не ожидает завершения POST, поэтому retVal может находиться в другом состоянии, чем вы ожидаете. Кроме того, если на этом сервере есть два пользователя, они смогут связываться с возвращаемыми значениями друг друга.

Salketer 28.05.2024 15:36

Если вызов остается ожидающим, это может означать, что на сервере произошла ошибка и клиент не получил ответа... Я думаю, что GetPage медленно обрабатывает или создает ошибку? Вы можете проверить журналы сервера и посмотреть, есть ли что-то необычное.

Salketer 28.05.2024 15:39

В дополнение к тому, что @Salketer правильно указал, что эта идея неверна, отсутствие обработки ошибок является #проблемным. В зависимости от версии node.js один неверный запрос может привести к сбою всего вашего сервера....

Jared Smith 28.05.2024 15:40

Ошибка возникает, даже если ответ будет постоянной строкой. Так что дело не в том, насколько быстр GetPage.

Bell Flo 28.05.2024 15:44

Не могли бы вы уточнить, как вы будете ждать ответа на запрос GET?

Bell Flo 28.05.2024 15:45

@BellFlo, чтобы внести ясность: у вас куча проблем с вашим кодом. Не стоит беспокоиться о проблеме, о которой вы спрашиваете, пока вы ее не устраните, потому что они могут быть причиной вашей проблемы, а могут и не быть. Используйте правильное управление состоянием, правильную обработку ошибок, правильную цепочку асинхронных задач, а если это по-прежнему не работает, вернитесь и обновите вопрос/задайте новый вопрос.

Jared Smith 28.05.2024 15:46
await fetch(post); await fetch(get); Ключевое слово await будет ждать разрешения промисов, прежде чем продолжить, а fetch возвращает промис. Кстати, как говорится, действительно странно публиковать данные и получать статус в другом вызове. Если сообщение изменяет что-то, что должно возвращать статус, сам запрос на публикацию должен возвращать статус, поэтому он будет атомарным во внешнем интерфейсе (и во внутреннем интерфейсе это должно быть сделано правильно и тоже быть атомарным. Вы должны прочитать о «атомарность», потому что у вас здесь куча проблем, поверьте мне, вам будет полезно узнать об атомарности в мире программирования).
Jorge Fuentes González 28.05.2024 15:49

Я благодарю всех за ответы, проблема заключалась в том, что я не знал, что можно связать получение и получение сообщения вместе, и это вызвало все остальные проблемы, а также причину моего запутанного серверного интерфейса. Я новичок в node.js - как, вероятно, показал вам код - и я благодарю всех за усилия, а также за стандарты stackoverflow - чрезвычайно приятные и полезные вопросы.

Bell Flo 28.05.2024 16:00
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
13
82
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Во-первых, я думаю, вы могли бы сократить ваши 4 звонка до одного.

app.post('/api/users/stats/post',(req,res)=>{
if (req.body){
const {pageNum,userPerPage}=req.body;
res.send(GetPage(Number(pageNum),Number(userPerPage)));
}else{
// Missing body, say that the input is bad.
res.sendStatus(422);
}
});

Одного этого достаточно.

Я удалил часть «side1», поскольку код точно такой же, как для стороны2. Итак, давайте сохраним только один маршрут и удалим эту побочную вещь.

Затем, поскольку POST использовался для «предварительной настройки» результата следующего GET, GET совершенно излишен, поскольку POST может просто вернуть результат напрямую. Устранение необходимости целого путешествия туда и обратно. В то же время это полностью устраняет проблему необходимости вызывать post перед get и гарантировать, что никто больше не вызовет post, пока я не вызову get.

У клиента тоже была пара ошибок. Во-первых, он не ждал завершения вызова POST перед вызовом GET. Поэтому вполне возможно, что GET получит предыдущее значение вместо правильного. Но мы исправили это, используя только одну конечную точку POST.

side1.addEventListener('click',()=>{
    fetch('/api/users/stats/post',{  
       method:'POST',
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side1.textContent,
        userPerPage:userPerSide
       })
    }).then(x=>x.text()).then(Txt=>{
    display.innerHTML=Txt;
    });
});
side2.addEventListener('click',()=>{
    fetch('/api/users/stats/post',{  
       method:'POST',
       headers:{'Content-Type':'application/json'},
       body:JSON.stringify({
        pageNum:side2.textContent,
        userPerPage:userPerSide
       })
    }).then(x=>x.text()).then(Txt=>{
    display.innerHTML=Txt;
    });
});

Теперь это снова становится немного менее сложным.

Есть и другая очистка кода, которую мы могли бы сделать, например, использование одного и того же прослушивателя событий для обоих объектов и т. д., но я пока оставляю это, чтобы прояснить ответ.

Чтобы внести ясность: это не решает проблему ОП. Но с кодом было много странных/неправильных вещей, и очистки, скорее всего, будет достаточно, чтобы исправить это естественным путем.

Salketer 28.05.2024 15:48

хорошо, значит, вы можете дождаться вызова get, связав выборку GET непосредственно с выборкой POST?

Bell Flo 28.05.2024 15:55

Чтобы уточнить, я использовал операторы GET и POST, потому что серверная часть жаловалась каждый раз, когда я просто использовал POST, так что, похоже, проблема заключалась в том, что у меня тогда было два отдельных оператора во внешней части?

Bell Flo 28.05.2024 15:56

Проблема с кодом заключалась в том, что у меня было два отдельных оператора выборки во внешнем интерфейсе.

fetch(post);
fetch(get);

Это заставило меня использовать два разных вызова метода на бэкэнде. Я узнал, что для получения ответа на запрос от сервера вам НЕОБХОДИМО использовать:

fetch(post).then(...);

Поскольку это говорит javascript дождаться завершения первой функции. Итак, мой главный недостаток в понимании заключался в том, что:

funcA().funcB(); -> synchronous
funcA();funcB(); -> asynchronous

Другие вопросы по теме