Implement Deferred object without using jquery

前端 未结 2 408
梦毁少年i
梦毁少年i 2021-02-04 16:38

I want to implement basic Deferred object without using jQuery. Here i will be implementing only done and fail callbacks, with resolve and reject functions. and ofCourse associa

相关标签:
2条回答
  • 2021-02-04 16:48
    function Deferred(){
      this._done = [];
      this._fail = [];
    }
    Deferred.prototype = {
      execute: function(list, args){
        var i = list.length;
    
        // convert arguments to an array
        // so they can be sent to the
        // callbacks via the apply method
        args = Array.prototype.slice.call(args);
    
        while(i--) list[i].apply(null, args);
      },
      resolve: function(){
        this.execute(this._done, arguments);
      },
      reject: function(){
        this.execute(this._fail, arguments);
      }, 
      done: function(callback){
        this._done.push(callback);
      },
      fail: function(callback){
        this._fail.push(callback);
      }  
    }
    
    
    var v;
    
    var setVal = function() {
        var d = new Deferred();
        setTimeout(function() {
            v = 'a value';
            d.resolve(this);
        }, 5000);
        return d;
    };
    
    setVal().done(function() {
        console.log('all done :' + v);
    });
    
    0 讨论(0)
  • 2021-02-04 17:10

    I think it's good to un-assign the callbacks after they are called to avoid memory leaks and also execute ones added later straight away.

    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)

    0 讨论(0)
提交回复
热议问题