【问题标题】:How to maintain request in Angular?如何在 Angular 中维护请求?
【发布时间】:2020-04-24 08:31:43
【问题描述】:

我有这个功能可以将服务中的对象保存在角度应用程序中。

save(object: Object): Observable<Book> {
  return this.http.put(this.baseUrl, object);
}

众所周知,http 请求是异步的,所花的时间可能比我们预期的要长。

在这种情况下,如果我经常调用这个函数save(object: Object)。会发生上一个请求尚未完成而下一个请求已发送的情况。这会导致问题。

我要保存的对象有一些独特的约束,例如名称和乐观锁。

查看以下一些案例:使用 obj1obj2

案例一: obj obj1和obj2同名不同ID;

obj1 {
  id: 1;
  name: 'name1';
  optimisticLock: 0;
}
obj2 {
  id: 2;
  name: 'name1';
  optimictic: 0;
}

在这种情况下,如果 obj1 已通过 http 发送但尚未完成,则 obj2 也已发送。对于 obj2,服务器端将检查名称是否重复。虽然我们可以看到 obj1 和 obj2 同名,但是因为那个 obj1 还没有被保存,所以 obj2 的名字检查会通过。所以obj2名字唯一性检查通过了,但是还是保存失败,服务器端会抛出唯一性约束异常。

案例 2 如果 obj1 和 obj2 是相同的数据但名称不同,如下所示:

obj1 {
  id: 0;
  name: 'previousName';
  optimisticLock: 0;
}
obj2 {
  id: 0;
  name: 'newName';
  optimisticLock: 0;
}

先发送obj1,再发送obj2保存。 obj1 保存和服务器端返回值是这样的

obj1 {
  id: 0;
  name: 'previousName';
  optimisticLock: 1;
}

它将更新它的乐观锁 0 -> 1;但是这个响应还没有返回到客户端,所以obj2optimisticLock仍然为0并发送到服务器端。显然,保存 obj2 的请求将失败。

我们期望的是保存最后的修改,但我们只保存了obj1。所以这是一个严重的问题。

我有一个想法来解决这两种情况。如果我使用队列来放置所有请求。所有请求都必须放入这个队列,这个队列发送第一个请求,在第一个请求得到响应之前,不会发送其他请求。在第一个请求响应后,根据响应更新此队列。然后发送第二个请求。

但是我不知道如何编写这个解决方案,有人知道怎么做吗?或者你有更好的解决方案来解决case1和case2中的问题吗?

【问题讨论】:

    标签: angular http request message-queue


    【解决方案1】:

    你可以使用 rxjs 来解决这个问题。您必须提供基于主题的触发器,然后调用 save 方法。

    例子:

    @Injectable()
    export class MyService {
    
      constructor(private httpClient: HttpClient) {}
    
      save(object: Object): Observable<any> {
        return this.httpClient.put('some-url', object);
      }
    
    }
    
    @Component({})
    export class MyComponent implements OnInit {
      save$: Subject<Object> = new Subject();
    
      constructor(private service: MyService) {}
    
      ngOnInit() {
        this.save$.pipe(concatMap(o => this.service.save(o)))
      }
    
      save(object: Object) {
        this.save$.next(object);
      }
    
    }
    

    有几个 rxjs/operators 来处理传入的事件。

    • concatMap 按顺序处理传入事件。在您的情况下,它会等到您的 http 请求完成,然后再执行下一个请求。所以基本上你的队列

    • 切换地图 从内部 observable 取消订阅并处理下一个事件。这意味着当前的 httpCall 被取消,下一个将被执行。最终最后一次保存会赢

    • 合并地图 每当一个事件进入一个新的内部 observable 时,都会创建并订阅一个新的内部 observable。这意味着无论前一个请求是否完成,您的所有请求都将被执行。

    • 排气图 这是不要打扰我的操作员。当内部 observable 未完成时,它会忽略所有传入的新事件。

    内部 observable 基本上是您的 httpCall,而外部 observable 是您的主题。在这个例子中,我使用了 concatMap,它将按顺序处理所有传入的保存操作,就像一个队列。

    【讨论】:

    • 问题是:如何根据最后的响应更新队列?
    猜你喜欢
    • 2013-11-25
    • 2021-12-26
    • 2011-10-26
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多