defer-promise搞定异步弹窗组件

最近在看vue组件库 Plain UI 时,发现一个比较有趣的异步弹框组件写法,操作如下:

(async ()=>{
    let message = await openDialog();
    console.log("弹窗信息",message)
})()

在异步函数中打开弹窗 openDialog 方法,当用户点击 confirm 按钮后,弹窗关闭,返回输入框信息。

openDialog方法可以很方便的通过promise实现,不过在看组件库源码时,发现对方是用defer 实现的,在promise兼容性还不是很好的时代 JQuery 就已经有 deferred.promise() 方法了,这里顺便也做了温习。

defer方法:

const defer = () => {
    const def = {}
    def.promise = new Promise((resolve, reject) => {
      def.resolve = resolve
      def.reject = reject
    })
    return def
}

defer方法其实返回的也是一个promise,并且将 resolvereject 方法拆开,这样我们就可以选择在适当的时机调用 resolve 或者 reject 方法了。

const dialogController = () => {
  let dfd = null

  const confirmBtn = document.getElementById('confirm')
  // 点击确定按钮
  confirmBtn.addEventListener('click', () => {
  // 隐藏弹窗
    dialogEl.hide()
  // resolve输入框信息给用户
    dfd.resolve(inputEl.value)
  })

  return () => {
    dfd = defer()
    dialogEl.show()
    return dfd.promise
  }
}

获得打开弹窗promise方法:

const openDialog = dialogController()

控制弹窗的打开,在异步函数中如果用户点击了弹窗确定按钮,关闭弹窗,获得输入信息。

const controlBtn = document.getElementById('control')
controlBtn.addEventListener('click', async () => {
  const message = await openDialog()
  console.log("弹窗输入框信息:",message)
})

这种方式可以方便我们封装常用的业务组件,之前在看 axios.cancel 源码时里面也是使用这种套路,灵活且实用。

通过 defer 方式实现的弹窗代码:


  
    defer promise
    
  
  
    

你可能感兴趣的:(javascript)