如何按请求列表顺序排序R中curl_fetch_multi的异步响应?
问题:异步HTTP请求响应按请求顺序排序
使用curl::curl_fetch_multi实现异步HTTP请求时,multi_run会并发执行请求,响应会按实际返回顺序存入data列表,但我们需要让data的顺序和初始request_list的请求顺序完全一致。
原代码中success回调直接追加元素到data,导致最终顺序随机(取决于响应快慢):
data <- list() success <- function(res){ cat("Request done! Status:", res$status, "\n") data <<- c(data, list(res)) } failure <- function(msg){ cat("Oh noes! Request failed!", msg, "\n") } request_list<-c("http://google.de","http://httpbin.org/status/418","https://bing.com") handles<-lapply(request_list,function(x)curl::curl_fetch_multi(x,success, failure)) curl::multi_run() str(data)
解决方案:绑定请求索引,定向赋值
核心思路是给每个请求绑定对应的索引位置,回调时直接把结果放到data的对应索引处,而非追加。这样不管响应返回顺序如何,最终data的顺序都会和请求列表一致。
修改后的完整代码:
# 初始化与请求列表长度一致的空列表,每个位置对应一个请求的结果 data <- vector("list", length(request_list)) success <- function(res, index){ cat("Request done! Status:", res$status, "\n") # 将响应存入对应索引的位置 data[[index]] <<- res } failure <- function(msg, index){ cat("Oh noes! Request failed!", msg, "\n") # 失败时给对应位置存入错误信息,方便后续处理 data[[index]] <<- list(error = msg) } request_list <- c("http://google.de", "http://httpbin.org/status/418", "https://bing.com") # 遍历请求时同时传递索引i,将索引绑定到回调函数中 handles <- lapply(seq_along(request_list), function(i){ target_url <- request_list[i] # 给回调函数传递当前请求的索引 curl::curl_fetch_multi( url = target_url, done = function(res) success(res, i), fail = function(msg) failure(msg, i) ) }) curl::multi_run() str(data)
关键说明
- 初始化
data为长度等于request_list的空列表,提前预留好每个请求的结果位置 - 使用
seq_along(request_list)获取每个请求的索引,确保每个请求对应唯一的位置 - 回调函数通过索引直接赋值,而非追加,彻底避免顺序混乱
- 失败请求也会在对应位置存入错误信息,不会出现缺失或错位
内容的提问来源于stack exchange,提问作者Andreas
相关产品推荐
相关产品推荐

