如何处理RxJS中的子顺序URL调用,这些子调用将数据相互传递?

时间:2019-05-02 10:42:28

标签: angular rxjs angular7 angular-httpclient rxjs6

我有一个服务调用,如果服务器正忙于处理响应,则该调用可能会向我返回队列URL。

我正在编写一个有角度的服务,以处理这些类型的调用,而且我正在努力找出哪种RXJS 6+运算符为我处理此操作。

这意味着我要回退,如果响应返回一个排队URL,我将订阅此呼叫,然后重试直到得到答案。

等待时间最长为30秒(< insert frustrations here>)。

根据我在rxjs文档页面上看到的信息,我需要使用concatMap运算符,并以某种方式retry进行调用,直到获得正确的响应为止?也许与某些delay接线员一起限制通话量?

我从snippet找到了https://www.learnrxjs.io/

谢谢!

2 个答案:

答案 0 :(得分:0)

如果我的假设不正确,但我将返回编辑此文件,但假设您需要在将请求重定向到队列时返回类似以下内容的有效负载:

using System;

protected void Page_Load(object sender, EventArgs e)
{
}

protected void Unnamed1_Click(object sender, EventArgs e)
{
    string excelPath = Server.MapPath("~/Files/") + Path.GetFileName(FileUploadBtn.PostedFile.FileName);
    FileUploadBtn.SaveAs(excelPath);

    string conString = string.Empty;
    string extension = Path.GetExtension(FileUploadBtn.PostedFile.FileName);
    switch (extension)
    {
        case ".xls":
            conString = ConfigurationManager.ConnectionStrings["Excel03ConString"].ConnectionString;
            break;
        case ".xlsx":
            conString = ConfigurationManager.ConnectionStrings["Excel07+ConString"].ConnectionString;
            break;
    }

    conString = string.Format(conString, excelPath);
    using (OleDbConnection excel_con = new OleDbConnection(conString))
    {
        excel_con.Open();
        string sheet1= excel_con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null).Rows[0]["TABLE_NAME"].ToString();
        DataTable dtExcel = new DataTable();

        dtExcel.Columns.AddRange(new DataColumn[3]
        {
            new DataColumn ("Name", typeof(string)),
            new DataColumn ("City",typeof(string)),
            new DataColumn ("Age",typeof(int))
        });

        using (OleDbDataAdapter oda = new OleDbDataAdapter("SELECT * FROM [" + sheet1+ "]", excel_con))
        {
            oda.Fill(dtExcel);
        }

        excel_con.Close();
        string consString = ConfigurationManager.ConnectionStrings["costumizadoConnectionString"].ConnectionString;
        using (SqlConnection con = new SqlConnection(conString))
        {
            using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(con))
            {
                sqlBulkCopy.DestinationTableName = "dbo.test";

                sqlBulkCopy.ColumnMappings.Add("Name", "Name");
                sqlBulkCopy.ColumnMappings.Add("City", "City");
                sqlBulkCopy.ColumnMappings.Add("Age", "Age");
                con.Open();
                sqlBulkCopy.WriteToServer(dtExcel);
                con.Close();
            }
        }
    }
}

相对于您刚收到回复时的情况:

<configuration>
  <connectionStrings>
    <add name="costumizadoConnectionString" connectionString="Data Source=PEDRO-PC\SQLEXPRESS;Initial Catalog=costumizado;Integrated Security=True; Provider=SQLNCLI10.1"
     providerName="System.Data.OleDb"  />
    <add name="Excel03ConString" connectionString="Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties='Excel 8.0;HDR=YES'" />
    <add name="Excel07+ConString" connectionString="Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties='Excel 8.0;HDR=YES'" />
  </connectionStrings>
</configuration>

重定向请求的方式可能如下

using (OleDbConnection excel_con = new OleDbConnection(conString))

答案 1 :(得分:0)

这是一个递归调用结构,因此您需要编写一个递归可观察的对象。您尚未提供确切的响应结构,所以我无法提供确切的代码,但从高层次来看,它看起来像这样:

getQueuedResponse<T>(url) {
  return this.http.get<T>(url).pipe( // fetch the first URL
    switchMap(res => 
      (res.queueUrl) // if queued (your actual queue indicator may be different)
        ? this.getQueuedResponse<T>(res.queueUrl) //then recurse (your actual next url may be different or it may be the original url again)
        : of(res))); // else break (what you actually return here may be different)
}

如果您希望使用简单的计时器,可以添加延迟时间:

getQueuedResponse<T>(url) {
  return this.http.get<T>(url).pipe( // fetch the first URL
    switchMap(res => 
      (res.queueUrl) // if queued, recurse after 5 seconds
        ? timer(5000).pipe(switchMap(t => this.getQueuedResponse<T>(res.queueUrl))
        : of(res))); // else break
}

或者,如果您的需求有所不同,并且可以反复调用相同的URL,则可以查看这是一个轮询问题:

pollForResponse<T>(url) {
  return timer(0, 5000).pipe( // start right away then emit every 5 seconds
    switchMap(i => this.http.get<T>(url)), // request the URL
    takeWhile(r => !!r.queued), // keep taking while it's queued
    last() // only emit the last response
  );
}