【问题标题】:Cannot get synchronization from inside subscribe to outside subscribe using localStorage or sessionStorage无法使用 localStorage 或 sessionStorage 从内部订阅同步到外部订阅
【发布时间】:2019-06-28 08:26:49
【问题描述】:

我有这个映射:

User     *----------------------------1     Role

从用户列表中,我去咨询这个列表中的一位用户。 要获取有关该选定用户的一些信息,我需要使用 localSorageinside subscribe 获取一个对象到 outside subscribe

下面是方法:

this.userService.getAllRolesOfActualUser(user.id).subscribe(listRoles =>
{

     let roles:Array<Role> = [];

     if (listRoles)
     {
         listRoles.forEach((role) =>
         {
             roles.push(new Role(role.id, role.name, role.selected));
         });
     }

     sessionStorage.removeItem("roles");
     sessionStorage.setItem("roles", JSON.stringify(roles));
     console.log("1. Inside Subscribe- " + user.id + "--------------: " + 
     sessionStorage.getItem("roles"));

});

console.log("2. Outside Subscribe- " + user.id + "--------------: " + sessionStorage.getItem("roles"));

user.service.ts 上,我有:

getAllRolesOfActualUser(id: number): Observable<any>
    {
        return this.http.get(`${this.baseUrl}/users/roles/${id}`);
    }

我的问题是,通常我得到的是之前咨询用户的值,而不是 screenshot 描述的实际用户 a:

你能帮我解决这个问题吗?!。 非常感谢。

【问题讨论】:

  • 简单来说,subscribe里面的代码是异步执行的。这意味着当执行到第二个console.log 语句时,subscribe 中的代码还没有被执行。原因是当你的 http 调用完成并且程序不知道它何时会发生时,它就会被执行,这就是它异步执行的原因。将您的第二个console.log 放入订阅块中,您将获得正确的结果。但我认为您正在尝试在其他地方同步使用roles,这不会解决您的实际问题。那你到底想做什么?
  • 感谢@ysf 先生的回复。但我需要订阅之外的那个对象,这就是真正想要做的。
  • 我需要roles 来填写清单,这将在订阅之外完成。
  • 请分享填写清单的代码。

标签: angular angular6


【解决方案1】:

你必须使用promise

    ses : String[];
    expertises : String[] = [];

    async getUri(userId: number)
        {
            let affected = this.userService.getExpertisesListByIdUserPromise(userId);

            await affected.then((uri) =>
            {
                this.ses = uri;
            })

            return this.ses;
        }

在 ngOnInit 上,我有

this.getUri(16).then(item => 
        {
            item.forEach(pro=>
            {
                this.expertises.push(pro);
            });
        });

在服务文件上,您有:

getExpertisesListByIdUserPromise(id: number): Promise<any>
    {
        return this.http.get(`${this.baseUrl}/users/expertises/${id}`).toPromise();
    }

HTH

【讨论】:

    【解决方案2】:

    我不确定您真正想要实现什么,但如果您想在示例下方直接获得“订阅之外”的结果,您可能必须以更同步的方式运行您的代码。

    例如,您可以使用 Promise 代替 Observable 并等待执行:

    await this.userService.getAllRolesOfActualUser(user.id).then(listRoles =>
    {
    
     let roles:Array<Role> = [];
    
     if (listRoles)
     {
         listRoles.forEach((role) =>
         {
             roles.push(new Role(role.id, role.name, role.selected));
         });
     }
    
     sessionStorage.removeItem("roles");
     sessionStorage.setItem("roles", JSON.stringify(roles));
     console.log("1. Inside Subscribe- " + user.id + "--------------: " + 
     sessionStorage.getItem("roles"));
    
    });
    
    console.log("2. Outside Subscribe- " + user.id + "--------------: " + sessionStorage.getItem("roles"));
    

    为您服务:

    getAllRolesOfActualUser(id: number): Promise<any>
    {
        return this.http.get(`${this.baseUrl}/users/roles/${id}`).toPromise();
    }
    

    【讨论】:

    • 您好@LeBavarois 先生,非常感谢您的回复。但是我收到了这个错误'await' expression is only allowed within an async function
    • 您需要将关键字async添加到您使用await的函数中。
    • 当我尝试使用 async await this.userService.getAllRolesOfActualUser(user.id).then(listRoles =&gt; 时,我得到了 Cannot find name 'async'
    • 好吧,也许我的评论有点不清楚。在其主体中使用 await 的函数必须具有 async 关键字。假设您想在选择用户时获取角色,您的代码可能如下所示:async onUserSelected(User user) { await this.userService.getAllRolesOfActualUser(user.id); // an so on }
    【解决方案3】:

    source 所以你必须使用 Promise:

          getData(){
                var promiseData =return new Promise((resolve, reject) => {
                  this.userService.getAllRolesOfActualUser(user.id).subscribe('........')
                        .subscribe(
                         data => {
    
        //your handlings
                          resolve(data)
                        },
                         error => {
                          reject(error);
                        },
                );
                    });
    return promiseData;
            }
    

    在您的控制器中:

    getData().then(data => {
          console.log(data);
    //do here what you want
        })
    

    如果你弄清楚了,只需测试一下并检查

    doAsyncTask() {
      let error = true;
       return new Promise((resolve, reject) => {
         setTimeout(() => {
           if (error) {
             reject('error'); // pass values
           } else {
             resolve('done'); // pass values
           }
         }, 1000);
       });
     }
    
     this.doAsyncTask().then(
      (val) => console.log(val),
      (err) => console.error(err)
    );
    

    *********我根据你的提议编辑

    doAsyncTask() {
      let error = true;
       return new Promise((resolve, reject) => {
         setTimeout(() => {
           if (error) {
             reject('error'); // pass values
           } else {
             this.userService.getExpertisesListByIdUserObj(2)
                    // .subscribe('........')
                    .subscribe(listExpertises =>
                          {
                            console.log("YES");
                              let exps:Array<Expertise> = [];
    
                              if (listExpertises)
                              {
                                  listExpertises.forEach((expert) =>
                                  {
                                      exps.push(new Expertise(expert.id, expert.name, expert.selected));
                                  });
                              }
    
                              sessionStorage.removeItem("exps");
                              sessionStorage.setItem("exps", JSON.stringify(exps));
                              console.log("1. MODIF-IN " + 2 + "--------------: " + sessionStorage.getItem("exps"));
    
                  });
             resolve('done'); // pass values
           }
         }, 1000);
       });
     }
    

    【讨论】:

    • 您好先生,非常感谢您的回复。但是,我得到了Property 'then' doesn't not exist on type Subscription
    • @ORBIT 先生您好,非常感谢您的回复。我在控制器上创建了 getData() 方法。我在 ngOnInit() 上调用了它,this.getData().then(data =&gt; { console.log("++++++++++++++++++++++" + data); }) 但我得到了任何东西,控制台没有显示
    • 更新的代码检查
    • 胡先生,我这样做了,但是控制台在 ngOnInit() 上生成:Object { __zone_symbol__state: null, __zone_symbol__value: [] } [object Promise]
    • 您好,先生,当我在 ngOnInit() 上调用 this.doAsyncTask().then( (value) =&gt; console.log(value), (error) =&gt; console.error(error) ); 时,我在控制台上得到了任何信息。但是我在函数上得到了正确的结果。
    【解决方案4】:

    从您的user.service.ts 中,您只从您的对象池(Array of Objects) 和您的component.ts 中获得一个对象您将有效负载保存为字符串化对象,以便获得所需的结果,您需要将其转换回JSON 通过做

    let role = sessionStorage.getItem('roles');
    let rolesObject = JSON.parse('role')
    
    console.log("1. LIST- " + user.id + "--------------: " +  rolesObject;
    

    我不知道您为什么要使用 array.push,但我认为您应该使用 listRoles 中的有效负载。

    【讨论】:

      猜你喜欢
      • 2021-08-15
      • 2020-10-17
      • 2012-01-19
      • 1970-01-01
      • 2018-05-25
      • 1970-01-01
      • 2018-06-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多