我正在创建一个由Node(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 />
}
asyncReq
是一个类似于以下内容的辅助函数:
export const asyncReq = endpoint => {
return
fetch( endpoint )
.then( res => { return res.ok ? res.json() : res } )
}
当请求成功以及遇到404
或500
错误时,这一切都很好。但是,假设我故意使用了错误的端点:
const apiBase = 'http://www.example.com'
export default {
news: wrongApiBase + '/news/'
// other endpoints
}
在这种情况下,由于wrongApiBase
未定义,Node给我以下错误:
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? )
}
+++更新+++
事实证明,我所产生的错误存在问题。就像我说的那样,我使用错误的变量名(wrongBaseApi
)来触发错误,这导致Node永远不会为页面提供服务。事后看来,这是有道理的,因为这是节点代码而不是传入请求的错误。
通过使用正确的变量但为其分配了错误的值(实际上是错误的API库,例如http://dahfjkdahfds.com
,这不是Node错误,而是请求错误),我能够使使用@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
}
和
export async function asyncReq( endpoint ) {
try {
const res = await fetch( endpoint )
return {
data: res.ok ? await res.json().then( val => { return val } ) : null,
error: res.ok ? false : res.status
}
} catch( error ) {
return { error }
}
}
答案 0 :(得分:2)
我认为您必须处理从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 };
}
}
答案 1 :(得分:0)
这不是一个好方法,但是我们可以通过在根节点上添加事件监听器来实现
window.addEventListener('unhandledrejection', rj => {
this.setState({hasError: true})
})
类似的东西。
答案 2 :(得分:0)
由于它是NodeJS,因此我将在process.on()
事件中使用window.addEventListener()
(而不是unhandledRejection
):
process.on("unhandledRejection", (err, promise) => {
console.log(`Unhandled rejection (promise: ${promise}, reason: ${err})`);
});
答案 3 :(得分:0)
比方说,您的getInitialProps调用asyncReq,后者又调用throwError方法。现在,如果throwError方法引发错误,则可以使用getInitialProps中的catch块来捕获它。因此,您应该始终在启动函数链的函数中放置catch块。为了更好地诊断错误,应在每个功能中放置catch块。但通常,在您调用的第一个函数中必须具有catch块。
var orders = allPendingOrdersCopy.Where(o => o.OrderDetails.Any())