【问题标题】:Making a sequence of async API calls to an external provider对外部提供者进行一系列异步 API 调用
【发布时间】:2022-02-18 18:45:36
【问题描述】:

我需要对外部提供者进行一系列 API 调用,每个调用都依赖于前一个调用的成功响应。每个调用方法都是异步的。以下代码是我处理此任务的方式。我担心这些调用可能不会按顺序调用,所以我想知道我是否做对了。

var client = await clientRepository.FirstOrDefaultAsync(c => c.UserId == userId).ConfigureAwait(false);

if (client == null)
    throw new Exception("Client Not Found");

// Send data to provider
var applicant = await apiClient.CreateApplicantAsync(client).ConfigureAwait(false);
if (applicant == null || applicant.Id.IsNullOrEmpty())
    throw new ApiException("Failed to create applicant");

// Send document a to provider
var documentResponse = await apiClient.UploadDocumentAsync(applicant.Id, dto.DocumentA.Stream, dto.DocumentA.FileName, dto.DocumentA.Document.Type).ConfigureAwait(false);

if (documentResponse == null)
    throw new ApiException("Failed to upload document");

// Send document b to provider
documentResponse = await apiClient.UploadDocumentAsync(applicant.Id, dto.DocumentB.Stream, dto.DocumentB.FileName, dto.DocumentB.Document.Type).ConfigureAwait(false);

if (documentResponse == null)
    throw new ApiException("Failed to upload document");

// Send applicant c to provider
var imageResponse = await apiClient.UploadApplicantImageAsync(applicant.Id, dto.DocumentC.Stream, dto.DocumentC.FileName).ConfigureAwait(false);

if (imageResponse == null)
    throw new ApiException("Failed to upload document");

// Check the applicant
var checkResponse = await apiClient.CheckApplicantAsync(applicant.Id).ConfigureAwait(false);

if (checkResponse == null)
    throw new ApiException("Applicant check failed");

// Check is successful when the Result property is null
if (checkResponse.Result.IsNullOrEmpty())
{
    result.Success();
}

【问题讨论】:

  • My concern is that these calls may not be called in sequence 是什么让你这么说?代码本身没有任何问题
  • 为什么不能使用 .Result ?

标签: c# .net asynchronous


【解决方案1】:

鉴于等待每个异步Task,您的代码将按顺序运行。但是,根据代码,您似乎可以同时执行上传任务(参见下面的示例)。

显示如何同时执行上传的示例:

var client = await clientRepository.FirstOrDefaultAsync(c => c.UserId == userId);
if (client == null)
    throw new ApiException("Failed to read client");

// Send data to provider
var applicant = await apiClient.CreateApplicantAsync(client);
if (applicant == null || applicant.Id.IsNullOrEmpty())
    throw new ApiException("Failed to create applicant");

// Send files a to provider
var docUploadA = apiClient.UploadDocumentAsync(applicant.Id, dto.DocumentA.Stream, dto.DocumentA.FileName, dto.DocumentA.Document.Type);
var docUploadB = apiClient.UploadDocumentAsync(applicant.Id, dto.DocumentB.Stream, dto.DocumentB.FileName, dto.DocumentB.Document.Type);
var imageUpload = apiClient.UploadApplicantImageAsync(applicant.Id, dto.DocumentC.Stream, dto.DocumentC.FileName);
await Task.WhenAll(docUploadA, docUploadB, imageUpload);
if (docUploadA.Result == null || docUploadB.Result == null || imageUpload.Result == null)
    throw new ApiException("Failed to upload document");

// Check the applicant
var checkResponse = await apiClient.CheckApplicantAsync(applicant.Id);
if (checkResponse == null)
    throw new ApiException("Applicant check failed");

// Check is successful when the Result property is null
if (checkResponse.Result.IsNullOrEmpty())
{
    result.Success();
}

【讨论】:

    【解决方案2】:

    鉴于您的代码,您的 API 请求不可能不按顺序调用。由于您直接等待每个调用,因此该代码的行为方式与同步代码相同。

    我不知道您的应用程序的用例,但如果此代码在某种形式的控制器中执行,您应该包含一个 CancellationToken 来取消这个长时间运行的脚本,以防用户中止请求。

    【讨论】:

      猜你喜欢
      • 2019-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-01
      • 2019-04-06
      • 2020-06-21
      相关资源
      最近更新 更多