0

我有两个角度服务调用,其中服务调用2应该在第一个服务调用的值的结果上进行。但是我的代码根本没有打第二次服务电话。请找到下面的代码片段。Angular2服务调用结果返回未定义,但填充数据

ngOnInit():void { let personId:string = this._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); 
    } 
} 
+0

谢谢你的解释,我也尝试如下,并将其错误,“无法读取的未定义的属性‘teamId’”,因为输入值“this.person.teamId”不可用。 this._teamService.getTeamById(this.person.teamId) .then(teamData => {if(this.person!== undefined){this。team = teamData; }}); –

+0

我无法想到可以避免回调问题的其他选择,任何帮助将不胜感激。 –

+0

谢谢。我添加了“console.log”来检查this.person.teamId值,因为我在浏览器开发人员工具上发生错误为“Can not read property'teamId'”。我已经添加了等待,因为你演示了它,它给了我一个编译错误,因为“无法找到名字等待”我是ANgular2的新手,请你纠正我。谢谢 –

回答

0

因为它返回一个Promise,所以将一个await添加到_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的结果。 console.log在getPersonById后立即被调用(某些ms),当不等待时,它在那个时刻没有值。

这是通过嵌套函数来完成上述操作的。请注意0​​。

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); 

当你调用返回一个承诺的功能,当时将首次承诺解决后调用。而随后.thens(你可以将它们添加)。 thens总是同步运行。太多这被称为“链”,被认为是不好的设计。无论您是否在等待,Thens都是顺序/同步的。

如果您希望outter函数等待(或“阻止”),以便同步运行,您也可以等待它们。

最后编辑: 我建议使用以下从其他SO answer复制了解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'); 
} 
+0

谢谢。我添加了“console.log”来检查this.person.teamId值,因为我在浏览器开发人员工具上发生错误为“Can not read property'teamId'”。我已经添加了等待,因为你演示了它,它给了我一个编译错误,因为“无法找到名字等待”我是ANgular2的新手,请你纠正我。谢谢 –

+0

您可以通过使函数异步来启用await关键字。通过在public和ngOnInit()之间添加'async'关键字来实现这一点。 – ttugates

+0

谢谢,它现在工作。几个问题。我的ngOnit()实际上是调用两个服务人员和团队,当我把我的函数作为异步时,它希望我返回一个值而不是void。我不确定我是否应该返回/可以返回两者,但我尝试了以下方式,现在可以使用。我不确定这是否是真正正确的书写方式。 'async ngOnInit():Promise {await this._personService.getPersonById(personId) .then(person => this.person = person); ....返回this.person; }' –

0

您的服务请求返回Promise,这是异步的 - 你的代码的其余部分将不会被调用then被阻塞。

所以您的控制台打印undefined,则if检查失败,并“然后”在未来某个时间你的服务调用返回和你的第一个then执行(第二个是永远不会因为你的if的执行)。

您可以通过将if声明放入您的then中来解决此问题,或研究一些技术以避免“回拨地狱”。