对外部提供程序进行一系列异步 API 调用

Making a sequence of async API calls to an external provider

我需要对外部提供程序进行一系列 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();
}

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

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

鉴于等待每个异步 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();
}