首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >响应错误边界,使异步函数不能正常工作

响应错误边界,使异步函数不能正常工作
EN

Stack Overflow用户
提问于 2019-07-11 18:58:23
回答 2查看 985关注 0票数 1

因此,基本上,我等待Auth从aws扩容/认知操作中返回当前经过身份验证的用户,然后运行一个查询来获取他们的数据(我故意让它出错,以便在这种情况下检查错误边界的功能)。我在client.ts中导入app.tsx并调用传递参数给它的getData函数,然后将axios错误对象返回给调用函数。我遇到了几个问题,并且无法让其中任何一个问题正常工作,如下所示:

  1. 如果我在data.error条件中设置了“抛出”,它就给了我明确的承诺,因为我不会手动拒绝()承诺。当我尝试这样做的时候,我会得到一些关于不能这样做的错误,因为组件没有那种类型的东西(我会重做并发布实际的错误)。
  2. 2)如果我使用基于state.hasError的条件在呈现函数中设置抛出,它会工作并命中错误边界,但会抛出一个错误,因为我没有捕获要抛出的错误。
  3. 如果我捕捉到在render函数中抛出的错误,它就会命中错误边界,但是会抱怨render()没有返回任何内容。

因此,从设计的角度考虑如何改进这个问题,我在这里发现的所有例子都是简单的例子,其中异步调用直接在组件中进行,错误直接在组件中处理,我不想真正这样做,因为我不喜欢重复代码,因为我只需要将代码传递给驻留在某个地方的函数就可以返回我想要的内容。

App.tsx:

代码语言:javascript
复制
async componentDidMount() {

      await Auth.currentAuthenticatedUser().then( data => {
        this.onGetAuthUser(data.username);
        var username = data.username;
        //rockset query --need to implement error handling elsewhere
        getData('select * from "ruzzleLeagueCollection" WHERE username=:username', 
        [{"name": "username",
        "type": "string",
        "value": data.username}]).then((data: any) => {

          if(data[0] != null) {
            if(data[0].error != null) {
             this.setState({error: true, errorData: data[0].error});
             return;
            }else {
             //get the logged in user.
            this.onGetLoggedUser(data[0]);
            }
          }else {
            //create the loggedUser object and pass it
            this.onGetLoggedUser([{
              username: username,
              ruzzleName: null,
              group: 0,
              hasProfile: false,
              currentSkill: null,
              highestSkill: null
            }])
          }
        });
      });  

  }
  render() {
    try{
    if(this.state.error) throw this.state.errorData;
    return (
      <div >    

          <Router>
            <div>
              <NavBar/>            
              <Switch>
                <Route exact path="/" component={Home}/>}/>
                <Route path="/players" component={Players} />
                <Route path="/season" component={Season} />
                <Route path="/records" component={Records} />
                <Route path="/stats" component={Stats}/>
                <Route path="/admin" component={Admin}/>
              </Switch>
            </div>
          </Router>

      </div>
    )
    } catch(err) {
      console.log('error caught!');
  }
  }

client.ts

代码语言:javascript
复制
import axios from 'axios';

const apiKey =  'fgf' //process.env.REACT_APP_ROCKSET_APIKEY;
const apiServer = process.env.REACT_APP_ROCKSET_APISERVER;

const url = apiServer + '/v1/orgs/self/queries';
const headers = { headers: {'Authorization': 'ApiKey ' + apiKey}};

var data = {'sql':{
    'query': '',
    'parameters': [
    ]}
}

//GET REQUEST
export async function getData(query: string, parameters: any) {
    data.sql.query = query;
    data.sql.parameters = parameters == null? undefined:  parameters;
    try {
        const response = await axios.post(url, data, headers)
        return response.data.results;
    }catch(err) {
        console.error('The following error occurred ' + err.message)
        if(err.response) {
            return handleErrors(err.response, 'response');

        }else if(err.request) {
            return handleErrors(err.request, 'request');

        }else {
           return handleErrors(err, 'other');

        }   
    }
} 

function handleErrors(error: any, errorType: string) {
    switch(errorType) {
        //this is a response error
        case 'response': 
            return [{error: {
                data: error.data,
                status: error.status,
                headers: error.headers
            }
            }]
        case 'request':
            return [{ error: 
                    { data: error.request}
                }]
        default:
            return [{error: {
                data: error.message}
            }]
    }
}

Errors.tsx:

代码语言:javascript
复制
export class Errors extends Component<any,IState>{
    constructor(props:any){
        super(props);
        this.state = {
            hasError: false,
            alertOpen: true,
            error: null,
            info: null
        };
    }

    componentDidCatch(e: any, info: any) {
        this.setState({
            hasError: true,
            error: e,
            info: info
        });
    }

      closeAlert() {
        this.setState({alertopen: false, hasError: false})
    }
      //render the error screen
      render() {
          if(this.state.hasError){
              var msg = 'Oops! Something went wrong. Error:  ' + this.state.info.componentStack;
              var title = 'Error in ' + this.state.error.data.message + ' ' + this.state.error.status;
          return(
            <div>
                <React.Fragment>
                    <AlertDialogSlide
                        open={this.state.alertOpen}
                        title = {title}
                        message= {msg}
                        closeAlert={() => this.closeAlert()}
                        error={true}
                    >     
                    </AlertDialogSlide>
                </React.Fragment>
            </div>
          )
      }
      return this.props.children;
    }

}

Index.js(入口点)--错误边界包装

代码语言:javascript
复制
ReactDOM.render(
    <Provider store={store}>
        <Errors>
            <App />
        </Errors>
    </Provider>
, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: 
serviceWorker.unregister();
EN

回答 2

Stack Overflow用户

发布于 2020-07-21 18:10:55

正如反应文档:Error边界中所述,而不是捕获异步代码的错误:

错误边界不会捕获以下错误:

  • 事件处理程序
  • 异步代码(例如setTimeout或requestAnimationFrame回调)
  • 服务器端呈现
  • 在错误边界本身抛出的错误(而不是其子边界)
票数 0
EN

Stack Overflow用户

发布于 2022-04-19 21:19:41

我在https://medium.com/trabe/catching-asynchronous-errors-in-react-using-error-boundaries-5e8a5fd7b971上发现了一个小黑客

它对我有效,为什么不..。

代码语言:javascript
复制
import { useCallback, useState } from "react";

/** A workaround for error boundary async limitations. */
export const useAsyncThrow = () => {
  const [_, setErr] = useState();
  return useCallback(
    (e) =>
      setErr(() => {
        throw e;
      }),
    [setErr]
  );
};

// Example:
// const asyncThrow = useAsyncThrow;
// (async () => asyncThrow(new Error()))();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56995736

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档