【问题标题】:Why does awaiting Promise.resolve(v) give you v but not awaiting gives you a promise?为什么 awaiting Promise.resolve(v) 给你 v 而不是 awaiting 给你一个 promise?
【发布时间】:2019-06-26 05:31:26
【问题描述】:

当我这样做时:

const p = Promise.resolve(‘hello world’);
console.log(p);

我得到这个输出:

ZoneAwarePromise {__zone_symbol__state: true, __zone_symbol__value: "hello world"}
__zone_symbol__state: true
__zone_symbol__value: "hello world"
__proto__: Object

但如果我这样做:

const p = await Promise.resolve(‘hello world’);

我得到这个输出:

hello world

为什么当我不等待 Promise.resolve(...) 时,p 是一个 Promise,但是当我等待时,p 是 Promise 解析为的值?

我问是因为据我了解, Promise.resolve(...) 不是异步的,这意味着它会立即解析。因此,在这两种情况下,p 不应该只是值“hello world”吗?如果 promise 已经解决,还有什么在等待?换句话说:从 promise 被解决到它为你提供解决的值之间会发生什么?是什么触发了这种情况?

【问题讨论】:

    标签: angular promise async-await


    【解决方案1】:

    函数Promise.resolve(val) 专门设计用于返回一个Promise 对象。这就是它的设计目的。所以,当你这样做时:

    const p = Promise.resolve('hello world');
    console.log(p);
    

    变量p 正好包含Promise.resolve() 旨在返回的内容,一个promise 对象。

    这个promise对象恰好已经在内部被解析了,但是当你检查返回值时,你看到的是这个Promise对象。

    与所有 promise 对象一样,如果您希望从 promise 对象中解析出值,则必须使用 .then()await 来访问该值。从Promise.resolve() 返回的承诺在这方面与任何其他承诺没有什么不同。

    const p = Promise.resolve('hello world');
    console.log(p);           // shows you the promise object
    
    p.then(val => {
        console.log(val);     // 'hello world'
    });
    
    // or this
    console.log(await p);     // 'hello world'
    

    为什么当我不等待 Promise.resolve(...) 时,p 是一个 Promise,但是当我等待时,p 是 Promise 解析为的值?

    因为Promise.resolve() 总是返回一个promise 对象,而await p 会从该promise 对象中获取值。

    我问是因为据我了解, Promise.resolve(...) 不是异步的,这意味着它会立即解析。因此,在这两种情况下,p 不应该只是值“hello world”吗?如果 promise 已经解决,还有什么在等待?换句话说:从 promise 被解决到它为你提供解决的值之间会发生什么?是什么触发了这种情况?

    当您想要的是已经处于已解决状态的 Promise 对象时,您使用 Promise.resolve()。如果您只想要一个值,则根本不使用Promise.resolve()。因此,这样的代码通常没有意义:

    const val = await Promise.resolve('hello world');
    

    你也可以这样做:

    const val = 'hello world';
    

    我将提供一个小例子。假设您有一个从其他服务器返回一些数据的函数,并且您有一个简单的缓存。该函数应始终返回一个承诺,因为它可能需要从另一台服务器获取数据(异步操作)。但是,有时您已经在本地缓存中拥有数据。您需要您的函数始终如一地返回一个承诺,以便调用者拥有一个干净且一致的 API。

     const cache = new Map();
     const rp = require('request-promise');
    
     function getData(id) {
         // see if we already have the result in the cache
         if (cache.has(id)) {
             // if so, return a promise that is resolved with our cached value
             return Promise.resolve(cache.get(id));
         } else {
             return rp(myURL + "?id=" + id).then(data => {
                 // cache the value
                 cache.set(id, data);
                 return data;
             });
         }     
     }
    

    在这个例子中,我们特别需要始终返回一个保证函数使用一致性的承诺。但是,当我们在缓存中有值时,我们希望返回一个已经解析的 Promise,其中包含我们的值。因此,我们专门为此使用Promise.resolve()

    然后调用者可以始终使用返回的 Promise,而不必知道该值是否被缓存:

     getData("price").then(val => {
         console.log(val);
     }).catch(err => {
         console.log(err);
     });
    

    【讨论】:

    • 感谢 jfriend,这很有道理。
    【解决方案2】:

    这正是await 所做的。在某种程度上,它可以被认为是“解包”一个 Promise——从语义上讲,您正在等待 Promise 解析,然后获取解析后的值。因此,您只能在异步函数(用 async 关键字指定)中使用 await,这会强制该函数的返回值本身为 Promise。

    所以,例如:

    async function example() {
      return await promise;
    }
    

    在功能上等同于:

    function example() {
      return promise.then(result => {
       return result;
      })
    }
    

    【讨论】:

    • 谢谢凯西,这很有道理。
    猜你喜欢
    • 1970-01-01
    • 2017-02-10
    • 2016-12-10
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 1970-01-01
    • 2017-06-06
    相关资源
    最近更新 更多