NodeJS JS:promise函数隐式地解包promise?

7nbnzgx9  于 9个月前  发布在  Node.js
关注(0)|答案(2)|浏览(146)

据我所知,Promises函数将其返回值隐式地 Package 到promise中。这对每个属性都有效,除了Promises本身。

async function f() {
  return new Promise((res) => {
    setTimeout(() => {
      res("Why am I being unwrapped")
    }, 1000)
  })
}

(async () => {
  console.log(await f())
})()

字符串
它们在返回之前被解包,所以await f()实际上等待两个嵌套的promise。
请注意,这也适用于显式删除的Promises(Promise.resolve(new Promise(...))
有没有一个的方法来避免这种情况?我真的很想有一个嵌套的Promise,而没有像这样的快速修复。

async function y() {
  return {wrapped: new Promise((res) => {
    setTimeout(() => {
      res("Why am I being unwrapped")
    }, 1000)
  })}
}

(async () => {
  console.log((await y()).wrapped)
})()


Sandbox

ne5o7dgx

ne5o7dgx1#

关于MDN documentation on async functions
异步函数总是返回一个promise。如果一个异步函数的返回值不是一个显式的promise,它将被隐式地 Package 在一个promise中。
换句话说,因为你返回的是一个Promise,所以它不会被 Package 。如果你想重新 Package 它,你可以,但是你也可以去掉async关键字,这有类似的效果。你会得到原始的Promise,除非你await它。
如此有效:

function f() {
  return new Promise((res) => {
    setTimeout(() => {
      res("Might be wrappers on some of you, but not on me!")
    }, 1000)
  })
}

(async () => {
  console.log(f())
})()

字符串
它会给你这样的输出:

Promise { <pending> }


如果目标是让一个Promise返回一个原始Promise,那么你将与Promise系统设计的所有功能做斗争,即在发现Promises时自动解包Promises。Promise.resolve() Package 了 * 但 * Promises的所有内容,如果你以某种方式给予Promise,它将递归地解包。
你可以通过返回一些不是Promise的东西来做到这一点,就像你的例子一样,但这似乎违背了Promise的整个目的。
如果你有一个特定的问题,你试图解决,绝对需要一个延迟的承诺,考虑返回一个函数,而不是一些任意的对象:

function f() {
  return () => {
    return new Promise((res) => {
      setTimeout(() => {
        res("I'll start as soon as you ask.")
      }, 1000)
    })
  };
}


然后,当你想得到一个真正的Promise时,你可以调用let p = f()和更高版本的p()。这是JavaScript通常处理延迟执行的方式。
如果你想立即启动Promise的执行,你仍然可以这样做:

function f() {
  const p = new Promise((res) => {
    setTimeout(() => {
      res("Already underway when requested.")
    }, 1000)
  })

  return () => { p };
}


虽然这些类型的技术通常是最好的避免,如果在所有可能的,通常他们是。

mkh04yzy

mkh04yzy2#

看起来你想要一个Future而不是一个Promise。你可以随意嵌套Futures,并且它们不会自动展开。本页解释了Futures和Promise之间的区别:https://en.wikipedia.org/wiki/Futures_and_promises
这里有一个方法来创造一个未来在TS...

export class Future<T> {
    static Pending = 0;
    static Resolved = 1;
    static Rejected = 2;
    state = Future.Pending;
    err;
    val: T;

    constructor(readonly p: Promise<T>) {
        p.then(val => {
            this.val = val;
            this.state = Future.Resolved;
        });
        p.catch(err => {
            this.err = err || new Error();
            this.state = Future.Rejected;
        });
    }

    async get(): Promise<T> {
        return this.p;
    }

    isDone(): boolean {
        return this.state != Future.Pending;
    }
}

字符串
对于JS,请删除类型描述符。

相关问题