使用 Promise.all() 和 put 方法获取时 JSON 输入意外结束

Unexpected end of JSON input when using Promise.all() and put method in fetch

我在使用 Javascript 时遇到问题,当时我尝试从 API 获取邮件内容并同时更新其阅读状态。控制台中的错误信息是:

SyntaxError: Unexpected end of JSON input
    at inbox.js:98

日志中的错误承诺如下。

1: Promise
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: SyntaxError: Unexpected end of JSON input at http://127.0.0.1:8000/static/mail/inbox.js:98:30
message: "Unexpected end of JSON input"
stack: "SyntaxError: Unexpected end of JSON input\n    at http://127.0.0.1:8000/static/mail/inbox.js:98:30"

第 98 行的代码是:

let res2 = response[1].json();

完整的js代码如下。我检查了名为 res1res2 的承诺。看来问题出在res2,因为它的return是rejected。我尝试了不同的方法来解决它,但都失败了。我也不明白为什么它没有被 catch 函数捕获。提前谢谢你。

虽然它每次 returns SyntaxErrorfetch 两个函数都已经工作了...

async function show_single_mail(email_id){
 
  // Show content of selected email

  document.querySelector('#mails_table').style.display = 'none';

  const email_div = document.createElement('div');
  document.querySelector('#emails-view').append(email_div);

  // Obtain email content and update its read status concurrently

  const option2 = {
    method: 'PUT', 
    body: JSON.stringify({read: true})}

  Promise.all([fetch(`/emails/${email_id}`), fetch(`/emails/${email_id}`, option2)])
    .then(response => {
      let res1 = response[0].json();
      let res2 = response[1].json();
      console.log([res1, res2]);
      return Promise.all([res1, res2])
    })
    .then(results => {
      result = results[0];
      email_div.innerHTML = 
      `<h3>Subject: ${result.subject}</h3><br>` +
      `<p>Sender: ${result.sender}</p><br>`+
      `<p>Receiver: ${result.recipients}</p><br>`+
      `<p>Time: ${result.timestamp}</p><br>`+
      `<p>Content: ${result.body}</p>`;
    })
    .catch(err => console.log(err))
}

您正在使用

执行两个并行请求
Promise.all([fetch(...), fetch(...)])

很好。但是当你处理你的结果时,你并没有检查请求是否成功,并且 fetch 不会拒绝 4xx 状态代码。此外,对于不成功的请求,您的服务器显然不会 return JSON 而只是文本。甚至可能是,第二个请求成功,但没有有效的 json 正文。没有人知道你的 API 到底是做什么的。

当你现在做的时候

.then(responses => {
   responses[0].json();  //this response has a valid json body
   responses[1].json();  //this one doesn't
})

response[1] 的正文无法解析为 json(responses[1].json() 试图这样做)。因此,抛出一个错误。所以你必须先检查一下,如果你的请求是 successful/returned json,然后你才能阅读他们的正文

.then(responses => {
   let s = responses.filter(x => x.ok);  //status == 2xx
   let f = responses.filter(x => !x.ok); //status != 2xx  
   //do something with failed requests and
   //only read the body for successful responses
   //return Promise.all(s.map(x => x.json()); 

   //or try to read json for successful and text for unsuccessful responsees
   //return Promise.all(responses.map(r => r.ok ? r.json() : r.text()));

   //or try to check the contenttype of the responses (if the server correctly sets them
   //return Promise.all(responses.map(r => r.headers.get("content-type").includes("application/json") 
   //    ? res.json()
   //    : res.text()
   //  ));
})
.then(responses => {
  //display them
});