Angular2服务调用结果返回未定义,但填充数据

Angular2服务调用结果返回未定义,但填充数据,angular,angular2-template,angular2-forms,angular2-services,Angular,Angular2 Template,Angular2 Forms,Angular2 Services,我有两个角度服务调用,其中服务调用2应该根据第一个服务调用的值的结果进行。但我的代码根本没有命中第二个服务调用。请在下面找到代码片段 ngOnInit():void{ 让personId:string=this.\u activatedRoute.snapshot.params['id'] this._personService.getPersonById(personId) .then(person => this.person = person); c

我有两个角度服务调用,其中服务调用2应该根据第一个服务调用的值的结果进行。但我的代码根本没有命中第二个服务调用。请在下面找到代码片段

ngOnInit():void{ 让personId:string=this.\u activatedRoute.snapshot.params['id']

    this._personService.getPersonById(personId)
        .then(person => this.person = person);

    console.log(this.person); --prints undefined but displays data within the html correctly.

    if (this.person) { 
    this._teamService.getTeamById(this.person.teamId)
            .then(teamData => this.team = teamData);
    }
}

您的服务调用正在返回一个
承诺
,这是异步的-对
然后
的调用不会阻止您的其余代码

因此,您的控制台将打印
未定义的
if
检查失败,并且在将来某个时间您的服务调用返回“then”,然后执行第一个
,然后执行第二个
(由于
if
),因此永远不会执行第二个


您可以通过将
if
语句放入
then
,或者研究一些技术来避免“回调地狱”来解决此问题。

向您的_personService.getPersonById添加等待,因为它返回承诺

只有在前面的等待完成后,才会点击console.log

    public async ngOnInit() {
        await this._personService.getPersonById(personId)
            .then(person => this.person = person)
            .catch(err => console.log(err));

        console.log(this.person); 

        if (this.person) { 
        await this._teamService.getTeamById(this.person.teamId)
                .then(teamData => this.team = teamData)
                .catch(err => {
                  // note curlys allow multiple statments.
                  // do work with error, log it etc..
                }
        }    
     }
至于为什么在HTML中看到值而不是控制台。HTML数据绑定一有值就会显示Promise的结果。在getPersonById之后立即调用console.log(一些毫秒),而在不等待时,它在该时刻没有值

这是如何通过嵌套函数来完成上述操作的。请注意
async person

public async ngOnInit() {

   await this._personService.getPersonById(personId)
        .then(async person => {
         // To Use await inside .then, add async like above
         this.person = person; 
         await this._teamService.getTeamById(this.person.teamId)
            .then(teamData => this.team = teamData)
            .catch(err => console.log(err) );
        })
        .catch(err => console.log(err));

    console.log(this.person);
当您调用返回承诺的函数时,then将在第一个承诺被解析后被调用。then(您可以添加它们)。then始终同步运行。太多的这被称为“链接”,被视为糟糕的设计。then是顺序/同步的,无论您是否使用WAIT

如果您希望outter函数等待(或“阻塞”)以便同步运行,那么您也需要等待它们

上次编辑: 我建议使用从另一个复制的以下内容来了解async/await

使用:

public delay(ms: number) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
调用以下命令并记下输出顺序。.添加和更改等待了解其行为

public async someFcn() {
   console.log('1');
   this.delay(2000)
      .then(x => console.log('2'));
console.log(3)
await this.delay(1000)
   .then(x => console.log('4')
   .then(x => console.log('5');
console.log('Done');
}

感谢您的解释,我确实尝试了以下操作,但出现了以下错误:“无法读取未定义的属性'teamId',因为输入值“this.person.teamId”不可用。this.\u teamService.getTeamById(this.person.teamId)。然后(teamData=>{if(this.person!==undefined){this.team=teamData;}}}});我想不出其他可以避免回调问题的方法,非常感谢您的帮助。谢谢。我添加了“console.log”来检查this.person.teamId值,因为我在浏览器开发人员工具上遇到了一个错误:“无法读取属性'teamId'”。我添加了Wait,正如您演示的那样,它给了我一个编译错误,如“找不到名称Wait”,我是ANgular2的新手,请您纠正我。谢谢。谢谢。我添加了“console.log”来检查this.person.teamId值,因为我在浏览器开发人员工具上遇到一个错误,“无法读取属性'teamId'”。正如您演示的那样,我添加了Wait,它给了我一个编译错误,即“找不到名称Wait”。我是ANgular2的新手,请纠正我。谢谢您可以通过使函数异步来启用Wait关键字。您可以通过在public和ngOnInit()之间添加
async
关键字来实现这一点.谢谢,现在开始工作了。几个问题。我的ngOnit()实际上正在调用两个服务人员和团队,当我将函数设置为异步时,它希望我返回一个值,而不是void。我不确定是否应该返回/可以返回这两个值,但我尝试了如下方法,现在它可以工作了。我不确定这是否是正确的编写方法。
async ngOnInit():承诺{等待这个。_personService.getPersonById(personId)。然后(person=>this.person=person);…返回this.person;}
所以这是一个稍微不同的问题,但是,ngOnInit()应该返回空,第二次呼叫也应该等待。我会更新我的答案,以反映所有的变化,包括一个catch语句和额外的信息。请考虑标记我的答案与复选框,如果你相信它回答你的问题。酷。谢谢你的所有信息。是的,我已经标记了它。