如何从Dart中的服务器API代码中抛出异常?

时间:2017-07-28 00:39:57

标签: dart rpc

我正在Dart中开发一个客户端 - 服务器应用程序,并且一直关注tutorial。我的服务器代码大致基于它。

在我的服务器API代码中,当出现问题时,我想抛出异常,例如:

void checkEverything() {
  if(somethingWrong)
    throw new RpcError(400, "Something Wrong", "Something went wrong!");
}

@ApiMethod(path: 'myservice/{arg}')
Future<String> myservice(String arg) async {
  checkEverything();
  // ...
  return myServiceResponse;
}

并且应该在主服务器中处理该异常,例如

// ...
var apiResponse;
try {
  var apiRequest = new HttpApiRequest.fromHttpRequest(request);
  apiResponse = await _apiServer.handleHttpApiRequest(apiRequest);
} catch (error, stack) {
  var exception = error is Error ? new Exception(error.toString()) : error;
  if((error is RpcError && error.statusCode==400) {
    // My code for creating the HTTP response
    apiResponse = new HttpApiResponse.error(
        HttpStatus.BAD_REQUEST, "Something went wrong", exception, stack);
  }
  else {
    // standard error processing from the Dart tutorial
    apiResponse = new HttpApiResponse.error(
        HttpStatus.INTERNAL_SERVER_ERROR, exception.toString(),
        exception, stack);
  }
}

(摘要,请参阅tutorial了解我的错误处理完整代码。)

但是,我的异常永远不会达到上述catch条款。相反,它似乎陷入了_apiServer.handleHttpApiRequest(apiRequest);,而这又引发了INTERNAL_SERVER_ERROR(500):

[WARNING] rpc: Method myservice returned null instead of valid return value
[WARNING] rpc:
Response
  Status Code: 500
  Headers:
    access-control-allow-credentials: true
    access-control-allow-origin: *
    cache-control: no-cache, no-store, must-revalidate
    content-type: application/json; charset=utf-8
    expires: 0
    pragma: no-cache
  Exception:
    RPC Error with status: 500 and message: Method with non-void return type returned 'null'

Unhandled exception:
RPC Error with status: 400 and message: Something went wrong!
#0      MyApi.myservice (package:mypackage/server/myapi.dart:204:24)
[...]

这对客户来说并不是非常具体。我想传达一个错误已经发生,而不是返回一个好看的回应。那么在Dart中处理服务器端异常并将该信息传递给客户端的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

好的,我想我解决了这个问题。 throw子句显然必须在API方法本身中,而不是在从属方法中。即:

@ApiMethod(path: 'myservice/{arg}')
Future<String> myservice(String arg) async {
  if(somethingWrong)
    throw new RpcError(400, "Something Wrong", "Something went wrong!");
  // ...
  return myServiceResponse;
}

而不是:

void checkEverything() {
  if(somethingWrong)
    throw new RpcError(400, "Something Wrong", "Something went wrong!");
}

@ApiMethod(path: 'myservice/{arg}')
Future<String> myservice(String arg) async {
  checkEverything();
  // ...
  return myServiceResponse;
}