【发布时间】:2021-05-02 02:03:14
【问题描述】:
我有使用 cra-universal 库制作的通用应用程序,当服务器没有收到 api 响应时,ssr 服务器停止并中断页面。我得到的错误是 UnhandledPromiseRejectionWarning: Unhandled Promise Rejection。此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未在 .catch() 中处理的承诺。要在未处理的 Promise 拒绝时终止节点进程,请使用 CLI 标志 --unhandled-rejections=strict
下面是我来自 cra-universal 的 ssr 服务器代码。
// import thunk from 'redux-thunk';
import { createReactAppExpress } from '@cra-express/core';
import { getInitialData } from '@cra-express/router-prefetcher';
import { HelmetProvider } from 'react-helmet-async';
// import Cookies from 'cookies';
import { getStoredState, persistCombineReducers } from 'redux-persist';
// import { CookieStorage, NodeCookiesWrapper } from 'redux-persist-cookie-storage';
import autoMergeLevel1 from 'redux-persist/lib/stateReconciler/autoMergeLevel1';
import storage from "redux-persist/lib/storage";
// import StyleContext from 'isomorphic-style-loader/StyleContext'
import routes from '../src/routes';
import {store} from '../src/index'
import {ChunkExtractor,ChunkExtractorManager} from '@loadable/server'
const path = require('path');
const React = require('react');
const { Provider } = require('react-redux');
const { StaticRouter } = require('react-router-dom');
const { createStore, applyMiddleware ,compose} = require('redux');
const { default: App } = require('../src/App');
const { default: reducer } = require('../src/redux/reducers');
const clientBuildPath = path.resolve(__dirname, '../client');
const statsFile=path.resolve(__dirname,'../dist/loadable-stats.json')
let tag = '';
//let store;
let AppClass = App;
let serverData;
let helmetCtx;
// console.log("REDUCERS",reducer)
const app = createReactAppExpress({
clientBuildPath,
universalRender: handleUniversalRender,
async onFinish(req, res, html) {
const { helmet } = helmetCtx;
const helmetTitle = helmet.title.toString();
const helmetMeta = helmet.meta.toString();
const newHtml = html
.replace('{{HELMET_TITLE}}', helmetTitle)
.replace('{{HELMET_META}}', helmetMeta);
res.send(newHtml);
},
onEndReplace(html) {
const state = store.getState();
//console.log("----SERVER getState----", store.getState());
return html.replace(
'{{SCRIPT}}',
`${tag}<script>
window.__PRELOADED_STATE__ = ${JSON.stringify(state).replace(
/</g,
'\\u003c'
)};
window.__INITIAL_DATA__ = ${JSON.stringify(serverData).replace(
/</g,
'\\u003c'
)};
</script>`
);
}
});
function handleUniversalRender(req, res) {
const context = {};
helmetCtx = {};
// const cookieJar = new NodeCookiesWrapper(new Cookies(req, res));
const persistConfig = {
key: 'root',
storage: storage,
// storage: new CookieStorage(cookieJar),
stateReconciler: autoMergeLevel1,
// stateReconciler(inboundState, originalState) {
// return originalState;
// }
};
let preloadedState;
getStoredState(persistConfig)
.then(preloadedState => {
//console.log("SERVER Preloded State", preloadedState);
})
try {
preloadedState = {
test: 'presisited Data'
};
} catch (e) {
preloadedState = {};
}
const rootReducer = persistCombineReducers(persistConfig, reducer);
/* store = createStore(
rootReducer,
preloadedState,
applyMiddleware(thunk)
);*/
// console.log("----SERVER getState----", store.getState());
// console.log("getInitialData",getInitialData)
return getInitialData(req, res,routes)
.then(data => {
const css = new Set();
const insertCss = (...styles) => styles.forEach(style => css.add(style._getCss()));
const extractor=new ChunkExtractor({statsFile})
const scriptTags = extractor.getScriptTags()
serverData = data;
// console.log("CSS FILES", scriptTags);
const app = (
<HelmetProvider context={helmetCtx}>
<StaticRouter location={req.url} context={context}>
<Provider store={store}>
{/* <StyleContext.Provider value={{ insertCss }}> */}
<ChunkExtractorManager extractor={extractor}>
<AppClass routes={routes} initialData={data} store={store}/>
</ChunkExtractorManager>
{/* </StyleContext.Provider> */}
</Provider>
</StaticRouter>
</HelmetProvider>
);
if (context.url) {
res.redirect(301, context.url);
return;
}
return app;
})
.catch(err => {
console.error(err);
res.sendStatus(500);
});
}
if (module.hot) {
module.hot.accept('../src/App', () => {
const { default: App } = require('../src/App');
AppClass = App;
console.log('✅ Server hot reloaded App');
});
module.hot.accept('../src/routes', () => {
console.log('✅ Server hot reloaded routes');
});
}
export default app;
有人可以帮我解决这个问题,因为我陷入困境并且必须尽早解决它。任何帮助或建议将不胜感激。
【问题讨论】:
标签: javascript node.js reactjs promise server-side-rendering