【问题标题】:Async Await and Promises - how to improve the syntaxAsync Await 和 Promises - 如何改进语法
【发布时间】:2019-02-02 07:30:32
【问题描述】:

如何创建语法糖来隐藏 .then 的一些复杂性?

给定下面的代码:

const Fridge = {
  async openDoor() {
    const myCake = new Promise(resolve => {setTimeout(()=> {
      console.log('door opened')
      resolve (Object.create(Cake))
    }, 2000)});
    await myCake
    return myCake
  }
}

const Cake= {
  eatCake(){ console.log ( 'yummy now I can eat my cake' ) }
}

const myFridge = Object.create(Fridge)

通常通过详细访问:

myFridge.openDoor().then(myCake=>{
  myCake.eatCake()
  ... other code here .....
}) // complicated

是否可以创建一些糖来代替:

myFridge.openDoor().eatCake()  //simple to understand .then implied

或者更进一步,而不是:

myObject.myPromise.then(res=>{
   let x = res
   ... do stuff with x
});

相当

let x = myObject.myPromise.res
... so stuff with x

从异步函数返回的任何内容都应该用于后续调用。并且假定所有后续代码都在 .then 中。 .then 的关闭由封闭函数的结尾决定(类似于 await 当前的工作方式)。

【问题讨论】:

  • 现在我想要一个蛋糕!非常感谢你!我在这里节食... :(

标签: javascript async-await es6-promise


【解决方案1】:

你可以在myFridge.openDoor()前面用括号括起来的await调用形成一个表达式,然后链接.eatCake()来调用从.openDoor()返回的对象的方法

(async() => {
  (await myFridge.openDoor()).eatCake()
})()

【讨论】:

  • 感谢您的回复,我想到了,但这仍然是一个半解决方案,这将导致这些仍然难以阅读/创建表达式:(await(await myFridge.openDoor())。吃蛋糕()).getFat()。但比 .then 好。
  • @TrevTheDev 不,代码不是“半解”。答案达到了问题中描述的要求。
  • 怎么样 (await(await myFridge.openDoor()).eatCake()).getFat() === myFridge.openDoor().eatCake().getFat() ?
  • @TrevTheDev 您在问题和上一条评论中假设性地描述的内容目前在实践中使用 JavaScript 是不可能的。答案中的代码使用表达式来实现基本相同或相似的模式,方法是为链接方法所需的每个 await 用法使用括号(一个表达式)。
  • 谢谢@guest271314,你对原型的想法让我陷入了一个兔子洞,这让我找到了代理,然后在经历了很多痛苦之后,发布了解决方案!
【解决方案2】:

有一种语法叫做try()catch() 在结合async await

示例:

async function someAsyncFunction () {
   try {
      const asyncValue = await asyncCall() //Promise
      console.log(asyncValue) // this will log only when asyncCall resolved
    }catch(error) {
     throw error
   }
  }

而不是使用 Promise 并链接 then() 并对其进行回调。

你做await asyncCall() 并且在此之下你可以继续编写更多具有解析值的代码 而不是用回调链接更多函数

很难解释和理解 1 英尺所以这里有一些 resource for async await

【讨论】:

  • 这如何适用于myFridge.openDoor().then
【解决方案3】:

这是一个提供语法糖的解决方案,可用于隐藏 await 和 .then 的复杂性:

const promiseNodeH = {
  get(target, prop) {
    if (prop in target || typeof prop !== 'string') return target[prop]
    return function() {
      const x = arguments
      const p3 = new Promise(resolve => {
        target.then(value => {
          resolve(value[prop](...x))
        })
      })
      return new Proxy(p3, Object.create(promiseNodeH))
    }
  }
}

const Cake = {
  eatCake(msg) {
    console.log(`starting to eat cake: ${msg}!`)
    const self = this
    return new Promise(resolve => {
      setTimeout(function() {
        console.log('cake eaten')
        resolve(self)
      }, 5000)
    })
  },
  getFat() {
    console.log('burp')
  }
}

const Fridge = {
  openDoor() {
    console.log('start to open door')
    const p1 = new Promise(resolve => {
      setTimeout(function() {
        console.log('door is open, here is your cake')
        resolve(Object.create(Cake))
      }, 5000)
    })
    return new Proxy(p1, Object.create(promiseNodeH))
  }
}

可以通过以下方式访问:

Fridge.openDoor().eatCake('Yummy').getFat()

【讨论】:

  • "这是一个避免 await 和 .then 的解决方案:" 除了模式没有避免.then()target.then(value => { resolve(value[prop](...x)) })
  • @guest271314 从接口的角度来看:它允许向下游用户公开一个没有 .then 并等待的 api。用户只需键入 Fridge.openDoor().eatCake('Yummy').getFat() - .then 并且不需要 await。
  • 答案开头描述模式的文字不真实和正确。该代码实际上并没有避免使用.then()
  • 如果您确信抽象符合问题的要求,那就这样吧。这并不意味着你可以让所有人相信你认为的“复杂性”是以某种方式隐藏的。 “复杂性” 是主观的。代码没有隐藏。一旦个人解开抽象(阅读源代码),答案中的代码可以被认为比简单地使用.then()await 具有更多的“复杂性”。无论如何,这是您的问题,而且您已经回答了自己的问题,显然令您满意,这很重要,因为这是您的问题。
  • @guest271314 大声笑,我希望让您相信我的论点的出色之处 - 哦,好吧,我必须满足于我无懈可击的自信;)。再次感谢您的挑战,它帮助找到了这个解决方案。
猜你喜欢
  • 2019-12-21
  • 1970-01-01
  • 2019-07-03
  • 2021-12-15
  • 2019-10-06
  • 2018-11-01
  • 2019-03-06
  • 2018-02-06
  • 2016-05-15
相关资源
最近更新 更多