function promise(fn){
  var P = 1,
  F = 2,
  R = 3;
  var state = P,
      value = null,handles = [];
  function fulFilled(res){
    state = F;
    value = res;
    handles.forEach(handle);
    handles = null;
  }
  function rejected(res){
    state = R;
    value = res;
    handles.forEach(handle);
    handles = null;
  }
  function handle(handler){
    if(state === P){
      handles.push(handler)
    }else{
      if(state === F&&typeof handler.onFulfilled === 'function'){
        handler.onFulfilled(value);
      }
      if(state === R&&typeof handler.onRejected === 'function'){
        handler.onRejected(value);
      }
    }
  }
  function resolve(res){
    try{
      var then = getThen(res);
      if(then){
        doResolve(then.bind(res),resolve,rejected)
        return;
      }
      fulFilled(res)
    }catch (e){
      rejected(e);
    }
  }
  function getThen(value){
    var type = typeof value;
    if(type === 'object'||type === 'function'){
       if(typeof value.then === 'function')
          return value.then
    }
    return null
  }
  function doResolve(fn,fulFilled,rejected){
    var done = false
    try{
      fn(function(res){
        if(done)return;
        done = true;
        fulFilled(res);
      },function(){
        if(done)return;
        done = true;
        rejected(res)
      })
    }catch (e){
      if(done)return;
      done = true;
      rejected(e)
    }
  }
  this.done = function(onFulfilled,onRejected){
    setTimeout(handle({
      onFulfilled,
      onRejected
    }
    ))
  }
  this.then = function(onFulfilled,onRejected){
    var self = this;
    return new promise(function(resolve,rejected){
      return self.done(function(res){
        if(typeof onFulfilled === 'function'){
          try{
            return resolve(onFulfilled(res))
          }catch(e){
            return rejected(e)
          }
        }else{
          return resolve(res)
        }
      },function(res){
        if(typeof onRejected === 'function'){
          try{
            return resolve(onRejected(res))
          }catch(e){
            return rejected(e)
          }
        }else{
          return rejected(res)
        }
      })
    })
  }
  doResolve(fn,resolve,rejected);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.