Javascript 如何处理节点错误';未经处理的承诺拒绝';那个页面被加载了?

Javascript 如何处理节点错误';未经处理的承诺拒绝';那个页面被加载了?,javascript,node.js,promise,Javascript,Node.js,Promise,我正在创建一个由节点(Express)服务器提供服务的Next.js应用程序,该服务器通过对API的请求来获取数据。我将请求端点保存在一个单独的api文件中: const apiBase = 'http://www.example.com' export default { news: apiBase + '/news/' // other endpoints } 然后我在getInitialProps中执行请求,并根据请求是否给出错误来执行条件呈现: static asyn

我正在创建一个由节点(Express)服务器提供服务的Next.js应用程序,该服务器通过对API的请求来获取数据。我将请求端点保存在一个单独的
api
文件中:

const apiBase = 'http://www.example.com'

export default {
    news: apiBase + '/news/'
    // other endpoints
}
然后我在
getInitialProps
中执行请求,并根据请求是否给出错误来执行条件呈现:

static async getInitialProps( { query: { slug } } ) {
    const news = await asyncReq( api.news + slug )
    return { news, error: news.status }
}

render() {
    return this.props.error ? <Error /> : <News />
}
当请求成功时,以及当我收到
404
500
错误时,这一切都可以正常工作。但假设我故意使用错误的端点:

const apiBase = 'http://www.example.com'

export default {
    news: wrongApiBase + '/news/'
    // other endpoints
}
在这种情况下,节点会给出以下错误,因为
erroapibase
未定义:

UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 498)
这是它应该做的,但是错误导致页面永远无法加载。我该怎么处理这个错误呢?我的想法是将一个
catch
语句链接到
asyncReq
,但我不确定应该从中返回什么,以便在
getInitialProps
中使用。我尝试返回
false
,但没有任何变化,页面无法加载

export const asyncReq = endpoint => {
    return 
        fetch( endpoint )
        .then( res => { return res.ok ? res.json() : res } )
        .catch( err => { // What should I return here? )
}
+++更新+++

事实证明,我产生的错误有一个问题。正如我所说,我使用了一个错误的变量名(
ErrorBaseAPI
)来触发一个错误,这导致节点从未为页面提供服务。事后看来,这是有道理的,因为这是节点代码的错误,而不是传入请求的错误

通过使用正确的变量但为其分配错误的值(实际上是错误的API基,例如
http://dahfjkdahfds.com
,这不是节点错误,而是请求错误),我能够使用@iKoala和@DEVCNN提供的try/catch块解决问题。所以我的代码变成:

static async getInitialProps( { query: { slug } } ) {
    const news = await asyncReq( api.news + slug )
    return { news }
}

render() {
    // this.props.news.data
    // this.props.news.error
}


我认为您必须处理asyncReq引发的错误:

static async getInitialProps( { query: { slug } } ) {
  try {
    const news = await asyncReq( api.news + slug )
    return { news, error: news.status }
  } catch (err) {
    // any error, including http error 40x and 50x
    return { news: null, error: err };
  }
}

这不是一个好方法,但我们可以通过在根节点上添加事件侦听器来实现

 window.addEventListener('unhandledrejection', rj => {
      this.setState({hasError: true})
    })

像这样的

由于它是NodeJS,我将使用
process.on()
(而不是
window.addEventListener()
)和
未处理的弹出事件:

process.on(“unhandledRejection”,(err,promise)=>{
log(`未处理的拒绝(承诺:${promise},原因:${err})`);
});

假设getInitialProps调用asyncReq,asyncReq又调用throwError方法。现在,如果throwError方法抛出错误,您可以使用getInitialProps中的catch块来捕获它。因此,您应该始终在启动函数链的函数中放置一个catch块。为了更好地诊断错误,应该在每个函数中放置catch块。但一般来说,必须在调用的第一个函数中使用catch块

getInitialProps = async function( { query: { slug } } ) {
try{
const news = await asyncReq( 'http://localhost:3000/' + slug )
return { news, error: news.status }
}
catch(err){
console.log('err:', err);
}
}

const throwError = () => {
throw 'New Error'
}

const asyncReq = endpoint => {
throwError();
return 
    fetch( endpoint )
    .then( res => { return res.ok ? res.json() : res } )
}

或者您可以在
getInitialProps
中使用
try catch
,并返回
{error:true}
始终捕获堆栈底部函数上的错误。它将捕获所有错误。更具体地说,在识别和处理错误时,您可以通过在每个函数上尝试捕捉来捕捉所有函数的错误。@DEVCNN我不确定我是否完全理解您的意思,抱歉,这里不是Javascript专家。你能提供一个简单的例子吗?谢谢你,但这对我不起作用,错误只是阻止了一切,我似乎从来没有真正得到过getInitialProps。我想我会尝试在asyncReqYes中移动try/catch块,如果您只想处理fetch调用中的错误,可以这样做。getInitialProps是首先被调用的方法吗?我看到您没有在任何地方调用render。你看到错误被记录了吗?如果你想加载它,你还需要在catch块中调用你的页面渲染器方法。我想我知道了(见更新的问题)。我选择iKoala的答案是因为他确实先回答了,但谢谢你的帮助!谢谢你,但这对我不起作用,错误只是阻止了一切,我似乎从来没有真正得到过getInitialProps。我想我会尝试在AsyncReq中移动try/catch块。您可以尝试使用
console.log
console.error
来记录抛出到catch块中的err对象,它会显示错误详细信息。另外,在您的问题中有两个版本的
asyncReq
,我建议的答案仅适用于第一个版本(no.catch块)。如果您使用的是第二版的
asyncReq
,答案应该不同,不要忘记在.catch块中打印错误对象。
 window.addEventListener('unhandledrejection', rj => {
      this.setState({hasError: true})
    })
getInitialProps = async function( { query: { slug } } ) {
try{
const news = await asyncReq( 'http://localhost:3000/' + slug )
return { news, error: news.status }
}
catch(err){
console.log('err:', err);
}
}

const throwError = () => {
throw 'New Error'
}

const asyncReq = endpoint => {
throwError();
return 
    fetch( endpoint )
    .then( res => { return res.ok ? res.json() : res } )
}