dvajs / dva

🌱 React and redux based, lightweight and elm-style framework. (Inspired by elm and choo)
https://dvajs.com/
MIT License
16.24k stars 3.16k forks source link

我在react-native中使用dva-no-router,在model中用Promise.reject,程序报错无法运行 #1271

Closed huang6349 closed 7 years ago

huang6349 commented 7 years ago

我在react-native中使用dva-no-router,在model中用Promise.reject,程序报错无法运行

import Dva from 'dva-no-router';

const app = Dva({
  onError: (error, dispatch) => {
    console.log('onError', error);
  },
});

function rejectPromise() {
  return Promise.reject('Failed');
}

app.model({
  namespace: 'count',
  state: 0,
  effects: {
    *throwError(action, { call }) {
      yield call(rejectPromise);
    }
  }
});

....

Actual behavior: (实际效果)

控制台抛出一段异常

'Unhandled promise rejection', 'Failed'

Versions of packages used: (哪个库的哪个版本出现的问题)

我使用的是 react@15.4.1 react-native@0.42.3 dva-no-router@1.0.2

xufei commented 7 years ago

reject 之后,你要 try catch 它。

try {
  yield call(rejectPromise);
} catch (ex) {
  throw ex;
}
huang6349 commented 7 years ago

@xufei

我尝试加入了你提供的 try catch 方案

import Dva from 'dva-no-router';

const app = Dva({
  onError: (error, dispatch) => {
    console.log('onError', error);
  },
});

function rejectPromise() {
  return Promise.reject('Failed');
}

app.model({
  namespace: 'count',
  state: 0,
  effects: {
    *throwError(action, { call }) {
      try {
        yield call(rejectPromise);
      } catch (error) {
        throw error;
      }
    }
  }
});

....

控制台任然会抛出这段异常

'Unhandled promise rejection', 'Failed'
sorrycc commented 7 years ago

在浏览器上能否重现?

nihgwu commented 7 years ago

核心代码逻辑有问题

https://github.com/dvajs/dva/commit/1ff02c21462120d9e9225f3892821c4261791f77 这个 commit 要保证 e 是一个 object 才行,test是抛出的 Error,而这里是直接 reject 一个 string,所以 _dontReject 和 preventDefault 都没有赋值成功

huang6349 commented 7 years ago

@sorrycc

我尝试在WEB端重写了这段代码,程序可以正常运行,但同样捕获的异常

Uncaught (in promise) Failed

但是在RN端,捕获到异常就不能运行了,我想这可能与RN上的Errors机制有关,RN会自动捕抓console.error()触发Errors弹出打印错误的界面,程序就停止了,而WEB端没有Errors这个机制,只会在控制台打印这个错误,

我本打算用Promise.reject(),拦截fetch的请求401和403状态,做出相应的全局权限验证,利用onError处理对应的逻辑,

huang6349 commented 7 years ago

@sorrycc

我尝试修改了dva-core lib中的 createPromiseMiddleware.js,将wrapped方法中的fn(args);注释了,使其不再控制台中抛出异常日志,这时,我RN的后续代码就能正常运行了

nihgwu commented 7 years ago

@huang6349 其实你直接reject 一个 object,然后在 onError 里面加 e.preventDefault() 就可以正常运行了

huang6349 commented 7 years ago

@nihgwu

我试了一下,果然可以,感谢大神的指导,非常感谢

nihgwu commented 7 years ago

不过这个地方确实是 dva 的bug @sorrycc

szwork2013 commented 6 years ago

到目前为止:dva-core lib中的 createPromiseMiddleware.js, wrapped方法中的fn(args) 还是没有修改!这个坑人的bug.

stechrayo commented 6 years ago

@huang6349 我把注释掉fn(args);之后dva的onError还是不能捕获到,请问你还做了其他处理吗?谢谢

我尝试修改了dva-core lib中的 createPromiseMiddleware.js,将wrapped方法中的fn(args);注释了,使其不再控制台中抛出异常日志,这时,我RN的后续代码就能正常运行了

huang6349 commented 6 years ago

@stelalae 我是用了nihgwu提供的方案,将异常终止了,

import Dva from 'dva-no-router';

const app = Dva({
  onError:(e)=>{
    e.preventDefault();
    // 在这里处理你的异常处理
  }
});
sunnypandas commented 5 years ago

@stelalae 我是用了nihgwu提供的方案,将异常终止了,

import Dva from 'dva-no-router';

const app = Dva({
  onError:(e)=>{
    e.preventDefault();
    // 在这里处理你的异常处理
  }
});

终止后类似 const { dispatch } = this.props; dispatch({ type: 'acgn/carouselListFetch', payload: {}, }).then(() => { const { acgn } = this.props; console.log('TEST STATE==============================:', acgn.carouselList); }); 还能用吗?我这边console.log('TEST STATE==============================:', acgn.carouselList);无输出。

huang6349 commented 5 years ago

可以用啊,这样处理了只是将 throw new Error 阻止传递了 除非你的 model 中的方法报错了,导致 then 没有被调用