Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
217 views
in Technique[技术] by (71.8m points)

javascript - UnhandledPromiseRejectionWarning: Unhandled promise rejection Error on CRA Universal app

I have universal app made with cra-universal library and when the server doesn't receive an api response the ssr server stops and breaks the page. the error that I am getting is 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 within .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict

below is my ssr server code from cra-universal.


// 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;

can someone please help me out with this one as I am stuck and have to resolve it at the earliest. Any help or suggestion will be greatly appreciated.

question from:https://stackoverflow.com/questions/65932664/unhandledpromiserejectionwarning-unhandled-promise-rejection-error-on-cra-unive

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Unhandled exceptions, promise rejections and logging can be handled using winston. If you only need to handle promise rejections and don't want to use third party tools, this can also be done using existing process variable e.g.:

process.on('unhandledRejection', (ex) => {
    console.log('unhandledRejection caught:');
    console.log(ex.message);
});

// This will create an unhandled promise rejectin
const p = Promise.reject(new Error('Failing with this promise..'));
p.then(() => console.log('Done!')); // Note 'Done!' will never get printed

Note: You MUST add process.on(..) before the problem occurs, since it adds a listener for these unhandled promise rejections. Adding it after the code where this rejections occurs will not catch this unhandled rejection. You should place this somewhere at the top of your code, just before all the logic happens e.g.:

...
const { default: reducer } = require('../src/redux/reducers');

process.on('unhandledRejection', (ex) => {
    console.log('unhandledRejection caught:');
    console.log(ex.message);
});

let tag = '';
let AppClass = App;
...

You can identically capture uncaught exceptions using keyword 'uncaughtException'.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...