是否可以根据条件重试一次?

丹尼斯·韦鲁

我有一个有效的方法,看起来基本上是这样的:

public IObservable<List<Stuff>> GetGoodStuff()
{
    return Observable.FromAsync(GetAccessTokenAsync)
        .SelectMany(accessToken =>
        {
            return httpClient.SendAsync(request);
        })
        .SelectMany(response => 
        { 
            response.EnsureSuccessStatusCode(); 
            return response.Content.ReadAsStringAsync(); 
        })
        .Select(json => 
        {
            return JsonConvert.DeserializeObject<List<Stuff>>(json);
        });
}

“ GetAccessTokenAsync”返回api的缓存访问令牌,否则,第一次将获取令牌。就httpclient和Rx而言,其余的都是非常标准的。

事情是这样的:我想捕获401错误,更新访问令牌,然后重试整个过程。但是只有一次-之后,它将异常抛出给调用者。

在该中间块中,我可以这样做:

            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                InvalidateAccessToken();
                // what now???
            }

但是那又怎样呢?没有看到递归调用将如何工作。不知何故包裹了整个东西?还没看到...

编辑1-7Nov2015

到目前为止,两个答案都不错。更具声明性的方法似乎没有多大变化,并且能够隐藏很多“管道”,但是我无法完全使它在所有情况下都能正常工作。

因此,根据@Timothy Shields的建议,我想到了此代码,它看起来不错,并且很好地隐藏了管道(是的,它可以工作:-)

/// <summary>
/// Makes an httpclient request using the access token. If Unauthorized is received the access
/// token will be reacquired and the request will be retried once.
/// </summary>
/// <returns>The json result from a successful request.</returns>
async Task<string> MakeRequestWithAccessToken(string requestUri, CancellationToken cancellationToken)
{
    const int RetryCount = 1;

    HttpResponseMessage response = null;
    for (int i = 0; i <= RetryCount; i++)
    {
        var accessToken = await GetAccessTokenAsync();

        var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
        request.Headers.Add("Authorization", "Bearer " + accessToken);

        var client = new RemoteService(ApiUrl).NewClient();

        response = await client.SendAsync(request, cancellationToken);
        if (i < RetryCount && response.StatusCode == HttpStatusCode.Unauthorized)
        {
            InvalidateAccessToken();
            continue;
        }

        response.EnsureSuccessStatusCode();
    }

    return await response.Content.ReadAsStringAsync();
}

public IObservable<List<Stuff>> GetGoodStuff(int maxCount)
{
    return Observable.FromAsync(async cancellationToken =>
    {
        var requestUri = string.Format("mypath.json?count={0}", maxCount);
        var json = await MakeRequestWithAccessToken(requestUri, cancellationToken);
        return JsonConvert.DeserializeObject<List<Stuff>>(json);
    });
}
蒂莫西·希尔兹

您应该使用async-await来做到这一点:

public IObservable<List<Stuff>> GetGoodStuff()
{
    return Observable.FromAsync(async cancellationToken =>
    {
        const int RetryCount = 1;
        for (int i = 0; i <= RetryCount; i++)
        {
            var accessToken = await GetAccessTokenAsync();
            var request = MakeRequest(accessToken);
            var response = await httpClient.SendAsync(request, cancellationToken);
            if (i < RetryCount && response.StatusCode == HttpStatusCode.Unauthorized)
            {
                InvalidateAccessToken();
                continue;
            }
            response.EnsureSuccessStatusCode();
            var json = await response.Content.ReadAsStringAsync(cancellationToken);
            return JsonConvert.DeserializeObject<List<Stuff>>(json);
        }
    });
}

这项技术使您可以编写标准命令式代码,并公开为nice IObservable<T>

请注意,我只是在猜测您的“重试”外观。调用后尚不清楚您要做什么InvalidateAccessToken(),所以我猜测了一下并发明了该MakeRequest方法。您应该很容易将其适应于完全符合您想要的代码。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

根据匹配条件查找最后一次出现

来自分类Dev

如何标记用户是否至少一次符合条件?

来自分类Dev

是否可以一次调用一次setjmp()多次执行longjmp()?

来自分类Dev

是否可以一次向熊猫DataFrame添加几列?

来自分类Dev

是否可以一次搜索多个Mongoose模型?

来自分类Dev

是否可以定义只能设置一次的变量?

来自分类Dev

是否可以一次搜索多个猫鼬模型?

来自分类Dev

是否可以一次调用多个方法或对象?

来自分类Dev

是否可以在一次呼叫中“解压”字典?

来自分类Dev

是否可以一次迭代多个 Dict 键?

来自分类Dev

为什么重试提示仅显示一次?

来自分类Dev

重试仅触发一次而不是多次触发

来自分类Dev

根据条件,每个循环将一个循环变量递增一次以上

来自分类Dev

如何根据javascript中的条件一次显示一张图片?

来自分类Dev

给定一个 for 循环内的 IF-ELSE 语句,我是否可以只在满足一次条件时跳过 IF?Python

来自分类Dev

在断开的电路上第一次重试后不会重试

来自分类Dev

如何根据一次应用于不同列的条件提取矩阵的行?

来自分类Dev

MYSQL内部联接仅根据两个条件计数一次

来自分类Dev

根据多列中的单个条件进行一次变量查找并呈现变量的出现

来自分类Dev

根据抛出的异常,是否可以对一个服务激活器使用2个不同的重试bean?

来自分类Dev

是否可以检测到您是否正在执行特定任务的最后一次尝试?

来自分类Dev

是否可以检测是否第一次调用 fluent interface?

来自分类Dev

根据是否是第一次运行应用程序检索正确的数据

来自分类Dev

是否可以仅对一次请求请求触发一个Github工作流程?

来自分类Dev

ZSH中是否有一种语法可以一次创建多个别名?

来自分类Dev

第一次单击后是否可以更改 iFrame 样式(不在同一域中)

来自分类Dev

NetLogo:可以一次在多个条件下选择补丁吗?

来自分类Dev

NetLogo:可以一次在多个条件下选择补丁吗?

来自分类Dev

根据条件进行条件汇总,然后每月重复一次组,使用dplyr更改日期间隔范围

Related 相关文章

  1. 1

    根据匹配条件查找最后一次出现

  2. 2

    如何标记用户是否至少一次符合条件?

  3. 3

    是否可以一次调用一次setjmp()多次执行longjmp()?

  4. 4

    是否可以一次向熊猫DataFrame添加几列?

  5. 5

    是否可以一次搜索多个Mongoose模型?

  6. 6

    是否可以定义只能设置一次的变量?

  7. 7

    是否可以一次搜索多个猫鼬模型?

  8. 8

    是否可以一次调用多个方法或对象?

  9. 9

    是否可以在一次呼叫中“解压”字典?

  10. 10

    是否可以一次迭代多个 Dict 键?

  11. 11

    为什么重试提示仅显示一次?

  12. 12

    重试仅触发一次而不是多次触发

  13. 13

    根据条件,每个循环将一个循环变量递增一次以上

  14. 14

    如何根据javascript中的条件一次显示一张图片?

  15. 15

    给定一个 for 循环内的 IF-ELSE 语句,我是否可以只在满足一次条件时跳过 IF?Python

  16. 16

    在断开的电路上第一次重试后不会重试

  17. 17

    如何根据一次应用于不同列的条件提取矩阵的行?

  18. 18

    MYSQL内部联接仅根据两个条件计数一次

  19. 19

    根据多列中的单个条件进行一次变量查找并呈现变量的出现

  20. 20

    根据抛出的异常,是否可以对一个服务激活器使用2个不同的重试bean?

  21. 21

    是否可以检测到您是否正在执行特定任务的最后一次尝试?

  22. 22

    是否可以检测是否第一次调用 fluent interface?

  23. 23

    根据是否是第一次运行应用程序检索正确的数据

  24. 24

    是否可以仅对一次请求请求触发一个Github工作流程?

  25. 25

    ZSH中是否有一种语法可以一次创建多个别名?

  26. 26

    第一次单击后是否可以更改 iFrame 样式(不在同一域中)

  27. 27

    NetLogo:可以一次在多个条件下选择补丁吗?

  28. 28

    NetLogo:可以一次在多个条件下选择补丁吗?

  29. 29

    根据条件进行条件汇总,然后每月重复一次组,使用dplyr更改日期间隔范围

热门标签

归档