httr2::last_response()与purrr::possibly()组合使用返回NULL的问题
解决httr2::last_response()与purrr::possibly()组合时的响应捕获问题
你遇到的问题核心是purrr::possibly()的otherwise参数是在定义函数时立即求值的,不是在函数执行出错时才调用。当你写otherwise = httr2::last_response()时,这个表达式在创建safe_request的瞬间就运行了——此时还没有发送任何请求,last_response()自然返回NULL,所以出错时就会返回这个预存的NULL,而不是去获取请求后的响应。
下面提供两种可行的解决方案,以及适配purrr批量迭代的扩展方法:
思路1:用httr2内置控制避免抛出错误
httr2的req_error()可以让请求不抛出HTTP错误,直接返回完整响应对象,不管状态码。这种方式不需要依赖全局的last_response(),逻辑更清晰:
library(httr2) library(purrr) library(stringr) # 定义不抛出HTTP错误的请求函数 request_without_error <- function(url) { url %>% request() %>% req_error(is_error = function(resp) FALSE) %>% # 所有状态码都不触发错误 req_perform() } # 测试单个请求 url <- str_c("https://mutalyzer.nl/api/normalize/", "GRCh37", "(", "NM_000546.5", "):", "c.673A>T") resp <- request_without_error(url) resp_body_json(resp) # 直接解析422状态的响应体
思路2:在possibly中延迟获取last_response()
如果一定要保留possibly的使用,需要把otherwise改成匿名函数,让它在错误发生时才执行last_response():
# 重新定义safe_request,让otherwise延迟求值 safe_request <- possibly( .f = \(url) url %>% request() %>% req_perform(), otherwise = \(httr2::last_response()), # 用函数包裹,错误触发时才执行 quiet = TRUE ) # 测试 result <- safe_request(url) resp_body_json(result) # 现在能正常获取422的响应体
适配purrr批量处理的可扩展方法
针对批量URL处理,推荐使用思路1,避免全局状态带来的意外覆盖问题,同时可以灵活处理不同状态的响应:
# 构造批量URL示例 urls <- c( str_c("https://mutalyzer.nl/api/normalize/", "GRCh37", "(", "NM_000546.5", "):", "c.673A>T"), str_c("https://mutalyzer.nl/api/normalize/", "GRCh37", "(", "NM_000546.5", "):", "c.1A>G") ) # 批量处理并按状态码分类结果 batch_results <- urls %>% map(request_without_error) %>% map(function(resp) { if (resp_status(resp) == 200) { list(status = "success", data = resp_body_json(resp)) } else { list(status = "error", code = resp_status(resp), detail = resp_body_json(resp)) } }) # 查看批量处理结果 batch_results
内容的提问来源于stack exchange,提问作者PeRiKo
相关产品推荐
相关产品推荐

