Angular 6避免回调地狱



来自AngularJS,我正在努力解决下一个问题。我需要一个返回对象的函数(让我们称之为a,但在该函数中包含的所有请求都得到解决之前,无法返回该对象

  1. 对象A是从远程服务器下载的
  2. 使用A,我们对另一个对象(B(执行操作
    1. B从服务器下载
    2. B使用A中的一些属性进行修补
  3. 使用AB的结果,我们对第三个对象执行操作,C
    1. C从服务器下载
    2. C使用AB中的一些属性进行修补
  4. 处理BC后,函数必须返回A

我想了解如何使用rxjs来做这样的事情,但对于Angular 6,互联网上的大多数示例似乎都不推荐使用,而且教程对我没有真正的帮助。我无法修改后端以使其更优雅。非常感谢。

考虑以下可观测值:

const sourceA = httpClient.get(/*...*/);
const sourceB = httpClient.get(/*...*/);
const sourceC = httpClient.get(/*...*/);

其中httpClient是Angular的HTTPClient。

您描述的操作顺序如下:

const A = sourceA.pipe(
switchMap(a => sourceB.pipe(
map(b => {
// do some operation using a and b.
// Return both a and b in an array, but you can
// also return them in an object if you wish.
return [a,b]; 
})
)),
switchMap(ab => sourceC.pipe(
map(c => {
// do some operations using a, b, and/or c.
return a;
}) 
))
);

现在您只需要订阅A:

A.subscribe(a => console.log(a));

您可以在此处阅读有关RxJs运算符的信息。

首先,在我看来,正如所描述的,这个函数调用将以某种方式阻止调用过程,直到所有指定的事件都发生为止——这在JavaScript中当然是不合理的。

因此,首先,我认为您的函数应该需要一个回调,作为它可能唯一的参数,当一切最终发生时,该回调将被调用。

现在,关于"如何优雅地处理步骤1、2和3">。。。立刻想到的是有限状态机(FSM(算法的概念。

假设您的函数调用会导致一个新的"请求"被放置在某个请求表队列上,如果需要,还会导致一个定时器请求(设置为在1毫秒内关闭(为该队列提供服务。(除其他外,该条目将包含对回调的引用。(我们还假设请求被赋予一个随机字符串"nonce",该字符串将用于唯一标识它:它将被传递给各种外部请求,并且必须包含在它们相应的回复中。

FSM的思想是,请求将具有状态(属性(,例如:DOWNLOADING_FROM_BB_DOWNLOADS_COMPLETEDOWNLOADING_FROM_CC_REQUESTS_COMPLETE等。这样,将在这个完全异步过程中发挥作用的每个回调都将(1(能够通过其nonce来定位请求条目,然后(2(明确地"知道下一步该做什么",以及"分配什么新状态(如果有(",仅基于对条目的state的检查。

例如,当状态达到C_REQUESTS_COMPLETE时,应该调用您最初提供的回调,并删除请求表条目。

你可以很容易地绘制出在任意复杂的场景中可能发生的所有"状态转换"(什么状态可以导致什么状态,以及当它们发生时该做什么(,无论你是否真的创建了一个数据结构来表示所谓的"状态表",尽管有时你这样做会更优雅(!(

当然,这是一种经典的算法,适用于"太阳下的每一种编程语言"。(许多硬件设备也使用它。(

最新更新