angular - 在另一个 promise 中立即更新该值后,将 from 运算符与 promise 一起使用时,Observable 获得错误的值

标签 angular ionic-framework async-await rxjs capacitor

我有一个 observable监听路由变化 :) 我也有一个 promise清除我的本地存储,完成后我立即更改路线,但我的 switchMap/switchMapTo在我的 route-change observable 中获取旧值..为什么会发生这种情况?
我已经尝试了很多方法来解决这个问题 - 我找到了两个可行的 :) 但我希望 了解 他们为什么工作。有人可以帮忙吗?这是关于 hot/cold observables 的事情吗?问题?也许与 event loop 有关的东西?我真的不知道:)

    this.storageService.clear().then((_) => {
      // this was successful!! And it was checked - user is deleted :)
      // now change the route and trigger the observable below :)
    });
    
    this.router.events.pipe(
      filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd)
      /*
        switchMap in here to get the user!
        Options 1 + 2 show that the user info exists!! 
        Although I know for sure that it was deleted.
        Option 3 + 4 work.
      */
    
      // 1) switchMapTo(from(this.storageService.getAsync<IUser>('user'))),
    
      // 2) switchMapTo(this.storageService.getAsync<IUser>('user')),
    
      // 3) switchMap(async (_) => {
      //      const y = await this.storageService.getAsync<IUser>('user');
      //      return y;
      //    }),
    
      // 4) switchMapTo(defer(() => this.storageService.getAsync<IUser>('user'))),
    );


    // Question edited for extra information - this is the getAsync function
    async getAsync<T>(key: string) {
        const result: GetResult = await Storage.get({ key });
        return JSON.parse(result.value) as T;
    }

最佳答案

急切与懒惰执行
发生这种情况是因为 Promise 是急切的,而 observable 是懒惰的。也就是说,一个 observable 在订阅之前不会做任何事情,而 Promise 从它被定义的那一刻起就会尝试解决它自己。
为了以最直接的方式解决这个问题,我将如何编写它:

this.router.events.pipe(
  filter((e: Event): e is NavigationEnd => e instanceof NavigationEnd),
  switchMap(_ => this.storageService.getAsync<IUser>('user'))
);
更新:
当然,不仅异步代码(如 promises 和 observables)可以具有急切/惰性求值语义。常规同步代码可能有相同的问题。由于在同步上下文中可能更容易理解问题,因此我将在下面创建一些示例来探索这一点,而无需使用 Promise 或 observables。

考虑这个不可观察的代码:
在第一个例子中,我们有一个函数 addNumbers这为您完成了两个数字相加的工作。它是急切的,所以它会立即完成工作,然后在调用后返回一个值。你可以在第 5 行看到,c()将等于 8。35在第 6 行相加,然后在第 8 行打印
function addNumbers(a, b){
  const answer = a + b;
  return () => answer;
}

const c = addNumbers(3, 5);

console.log("This should be an 8:", c());
在下一个例子中,我们有一个非常相似的函数,但它是惰性的。它记住你给它的数字,但它实际上并没有添加数字,直到有东西调用它。在这种情况下,c需要调用c()之前35实际上以任何方式使用。 53直到第 7 行才加在一起。
function addNumbers(a, b){
  return () => a + b;
}

const c = addNumbers(3, 5);

console.log("This should be an 8:", c());
懒惰与急切的后果
考虑这两个例子。如果您了解他们为什么打印不同的值,您就会了解手头的问题:)
示例 1:
const a = { n: 3 };
const b = { n: 5 };

function addNumbers(v1, v2) {
  const answer = { n: v1.n + v2.n };
  return () => answer;
}

const c = addNumbers(a, b);

a.n = 7;

console.log('Eager Evaluation:', c());
在这里,c.n等于 3 + 5因为 c之前评估过 a.n被设置为 7 .这与您在删除用户之前检索用户时的情况相同。它没有看到用户信息在此期间发生了变化,因为已经计算了该值。
示例 2:
const a = { n: 3 };
const b = { n: 5 };

function addNumbers(v1, v2) {
  return () => ({ n: v1.n + v2.n });
}

const c = addNumbers(a, b);

a.n = 7;

console.log('Lazy Evaluation:', c());
这里,c.n 等于 7 + 5因为 c 被评估 a.n被设置为 7 .这与您使用 defer 检索用户时相同.这次我们检查a.n的值c()的那一刻被评估,而不是在 addNumbers(v1, v2) 时被评估。
看到不同?

关于angular - 在另一个 promise 中立即更新该值后,将 from 运算符与 promise 一起使用时,Observable 获得错误的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69560421/

相关文章:

angular - <ng-template></ng-template> 正在加载多次

javascript - 如何将状态更改解析为嵌套 View 上的 Controller

javascript - Angular 工厂不工作

asp.net - 在 ASP.NET 中调用异步方法时的令人困惑的行为

c# - volatile IEnlistmentNotification 和 TransactionScope.AsyncFlowEnabled = true

angular - 未知元素 - Angular 2 与 Angular 2 Material

angular - 测试 - 没有 TranslateService 的提供者

javascript - 作为对象参数的动态路径

c# - 在方法中使用SemaphoreSlim而不进行异常处理

html - Angular - 如何直接修改组件内 HTML 元素的 CSS 转换属性