【问题标题】:Pure JavaScript $.Deferred纯 JavaScript $.Deferred
【发布时间】:2018-02-22 12:15:12
【问题描述】:

如果没有 jQuery,我将如何编写以下内容?

var dfd = $.Deferred()
dfd.done(done)
dfd.resolve()

function done() {
   console.log('done')
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【问题讨论】:

  • 不能直接使用 ES6 Promise 吗?另外,您的延迟(又名承诺)无需任何异步工作即可直接解决,但我猜您的实际用例不同?
  • 是的,我可以。是的,我的现实生活用例需要等到其他事情发生。
  • Deferreds 现在几乎被认为是一种反模式,ES6 不直接支持它们是有原因的。你真正想解决什么问题?任何关于 ES6 标准 Promise 的基础教程都将向您展示如何使用 Promise 执行器创建和解决标准 Promise。您是否特别询问如何在 ES6 中创建延迟对象(现在不受欢迎的东西)?或者这里要解决的真正问题是什么?有了尽可能多的代表,你应该能够写出一个更完整、更有意义的问题。
  • 有关将延迟(而不是承诺)作为反模式的讨论,请参见此处:When would someone need to create a deferred?
  • 并且,有关使用标准承诺创建延迟的示例,请参阅here

标签: javascript promise


【解决方案1】:

使用原生promises

Promise
  .resolve()
  .then(done);

function done() {
   console.log('done')
}

更新

没有链条:

let op = Promise.resolve();
op.then(done);

function done() {
   console.log('done')
}

【讨论】:

  • 有没有办法把它分成两行代码而不是一条链?
  • 有没有办法将let op = Promise.resolve(); 分成两行?
  • 嗯,我不明白你为什么需要这个,但也许这个:let promise = Promise; op = promise.resolve()?
【解决方案2】:

    function Deferred (){
      let res,rej,p = new Promise((a,b)=>(res = a, rej = b));
      p.resolve = res;
      p.reject = rej;
      return p;
    }

你只需要暴露 resolve 和 reject 就可以了。

【讨论】:

    【解决方案3】:

    使用本机 Promise 的问题在于,在回调中提供了解析和拒绝处理程序,因此如果您在实际分配它们之前尝试调用它们。

    在我看来,例如自己实现一个 deferred 会更健壮:

    function deferred() {
      let thens = []
      let catches = []
    
      let status
      let resolvedValue
      let rejectedError
    
      return {
        resolve: value => {
          status = 'resolved'
          resolvedValue = value
          thens.forEach(t => t(value))
          thens = [] // Avoid memleaks.
        },
        reject: error => {
          status = 'rejected'
          rejectedError = error
          catches.forEach(c => c(error))
          catches = [] // Avoid memleaks.
        },
        then: cb => {
          if (status === 'resolved') {
            cb(resolvedValue)
          } else {
            thens.unshift(cb)
          }
        },
        catch: cb => {
          if (status === 'rejected') {
            cb(rejectedError)
          } else {
            catches.unshift(cb)
          }
        },
      }
    }
    
    const d = deferred()
    
    setTimeout(() => {
      d.resolve('good')
    }, 1000)
    
    // Will be called after 1s
    d.then(value => console.log('#1 resolved!', value))
    
    setTimeout(() => {
      // Will be called after 3s and executed right away as it's already resolved
      d.then(value => console.log('#2 resolved!', value))
    }, 3000)

    【讨论】:

      猜你喜欢
      • 2017-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多