简体   繁体   English

可观察到的诺言嵌套在诺言中

[英]Observable as promise nested in promise

I'm in a scenario where I have a promise inside a promise . 我在一个场景中,我有一个promise一个内部的promise However when calling .then on the containing promise I'm getting the result of my inner promise. 但是.then在包含promise调用.then.then我得到的是内部承诺的结果。 Which is great, but I don't understand why it works. 很棒,但是我不明白为什么会起作用。 Why can I do this: 我为什么可以这样做:

    this.dataService.init().then(d => console.log(d));

instead of this: 代替这个:

    this.dataService.init().then(p => p.then(d => console.log(d));

dataservice DataService的

  init(){
    return this.geo.init().then( p => this.get(p.lat, p.lon));
  }

  get(lat, lon){
    let uri = `${this.baseuri}lat=${lat}&lon=${lon}&appid=${this.appid}`
   //this returns a promise
    return this.http.get(uri).toPromise()
      .then(d => d.json() || {}); 
  }

geolocation service 地理位置服务

  init(){
    return new Promise( this.getGeolocation );
  }

When you return a promise from inside a .then() handler, the outer promise and the inner promise become chained together. 当您从.then()处理程序内部返回承诺时,外部承诺和内部承诺会链接在一起。 The outer promise will then get its value from the inner promise and the outer promise will not call it's .then() handlers until the inner promise is resolved. 然后,外部承诺将从内部承诺中获取其值,并且在内部承诺得到解决之前.then()外部承诺不会调用它的.then()处理程序。

This is a very powerful and intentional feature of promises. 这是promise的非常强大和有意的功能。 It allows you to very easily sequence async operations and know what the eventual and final result is. 它使您可以非常轻松地对异步操作进行排序,并知道最终结果是什么。

A promise never resolves with a value that is another promise. 一个承诺永远不会以另一个承诺的价值来解决。 When it detects that you returned a promise from a .then() handler, it just chains to that promise and uses that new promise's value as the eventual value for the parent promise. 当它检测到您从.then()处理程序返回了一个诺言时,它只是链接到该诺言并将该新诺言的值用作父诺言的最终值。

In fact, you can't even purposely make a promise be the resolved value from within a .then() handler. 实际上,您甚至无法有意识地做出承诺,即从.then()处理程序中解析出的值。 In rare cases where you want a resolved value to be a promise, you have to wrap it in an object (to hide it) and resolve with the non-promise object as the resolved value. 在极少数情况下,您希望将已解决的值作为承诺,则必须将其包装在一个对象中(以将其隐藏),然后将非承诺对象作为已解决的值来解决。

So, in this line: 因此,在这一行:

return this.geo.init().then( p => this.get(p.lat, p.lon));

Here's the sequence of operations: 操作顺序如下:

  1. Call this.geo.init() . 调用this.geo.init() That returns a promise, we will call p1 . 这返回了一个承诺,我们将调用p1
  2. Call .then() on that promise and pass it a callback. 在该.then()上调用.then()并将其传递给回调函数。 This registers the .then() callback handler to be called later with the previous promise resolves. 这将注册.then()回调处理程序,以供以后在先前的promise解析后调用。 It also returns a new promise which is what is returned from your function. 它还返回一个新的promise,这是您的函数返回的结果。 We will call this promise p2 . 我们将这个承诺称为p2 This is one of the keys that allows this to work. 这是使它起作用的关键之一。
  3. Now p1 resolves eventually. 现在p1最终解决。 This calls the .then() handler callback registered on it. 这将调用在其上注册的.then()处理函数回调。 This calls this.get(...) which returns another promise p3 which is returned from inside this .then() handler as the return value. 这将调用this.get(...) ,它返回另一个从该.then()处理函数内部返回的promise p3作为返回值。
  4. The promise infrastructure sees that you returned a promise from the .then() handler so it links p2 to p3 and p2 does not get resolved until p3 does and when p3 does finally get resolved, p2 uses its resolved value. Promise基础结构会看到您从.then()处理程序返回了.then()因此它将p2链接到p3并且p2直到p3得到解析,而p3最终得到解析时, p2才会使用其已解析值。 The key that makes this work is that p1 is long since resolved, but p1.then() returned a new promise p2 which is what your top level function returned. 进行此工作的关键是p1早已解决,但是p1.then()返回了一个新的承诺p2 ,这是您的顶级函数返回的内容。 And p2 gets chained to p3 so p2 does not resolve until p2 does and p2 gets its resolved value from p3 . 而且p2链接到p3因此p2直到p2解析并且p2p3获得其解析后的值时才解析。

FYI, you can chain to any arbitrary depth. 仅供参考,您可以链接到任意深度。

The dataService.init function returns a promise. dataService.init函数返回一个dataService.init When you invoke a function that returns a promise, the parameter that is passed to .then() is what you get AFTER the promise has resolved. 当您调用返回诺言的函数时,传递给.then()的参数就是在诺言得到解决之后得到的。 A promise cannot resolve and return ANOTHER promise to its .then callback. 一个承诺不能解决,并将ANOTHER承诺返回到其.then回调。 It must wait until the inner promise resolves first. 它必须等到内在的诺言首先解决。

this.dataService.init().then(d => console.log(d));

When your callback receives d , both promises have already resolved, and d is a value, NOT a promise. 当您的回调收到d ,两个承诺都已经解决,并且d是一个值,而不是一个承诺。 Therefore it doesn't make sense to call .then() on it again. 因此,再次调用.then()没有意义。

Essentially, you can nest functions that return promises as much as you like . 本质上, 您可以嵌套返回期望值的函数 When you call the outermost function, it will wait until all the promises have resolved before returning the final value. 当您调用最外层函数时,它将等待直到所有的Promise都解决之后才返回最终值。

For instance: 例如:

const getXhrResult = () => axios.get('/some-url') // returns a promise

const func1 = () => getXhrResult().then((res) => {
  console.log('Got the result')
  return result * 2 // also returns a promise
}

const func2 = () => func1().then(console.log)

func2() // logs the result * 2.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM