Skip to content

Instantly share code, notes, and snippets.

@briancavalier
Created February 7, 2011 12:55
Show Gist options
  • Save briancavalier/814318 to your computer and use it in GitHub Desktop.
Save briancavalier/814318 to your computer and use it in GitHub Desktop.
A closure version of my mod (https://gist.github.com/814313) to unscriptable's tiny promise (https://gist.github.com/814052/)
function Promise() {
var callbacks = [],
promise = {
resolve: resolve,
reject: reject,
then: then,
safe: {
then: function safeThen(resolve, reject) {
promise.then(resolve, reject);
}
}
};
function complete(type, result) {
promise.then = type === 'reject'
? function(resolve, reject) { reject(result); }
: function(resolve) { resolve(result); };
promise.resolve = promise.reject = function() { throw new Error("Promise already completed"); };
var i = 0, cb;
while(cb = callbacks[i++]) { cb[type] && cb[type](result); }
callbacks = null;
}
function resolve(result) {
complete('resolve', result);
}
function reject(err) {
complete('reject', err);
}
function then(resolve, reject) {
callbacks.push({ resolve: resolve, reject: reject });
}
return promise;
};
@souparno
Copy link

souparno commented Nov 17, 2018

why is the while loop necessary in the complete function ?
can that not be just a
cb[0](result); cb.shift();

@Sylvenas
Copy link

Sylvenas commented Aug 4, 2021

With the help of your idea, implemente a fully method promise

function MyPromise(fork) {
  let callbacks = [];
  let promise = {
    val: null,
    status: "pending",
    resolve: resolve,
    reject: reject,
    then: then,
    finally: finallyFun,
    catch: catchFun
  };

  function complete(type, result) {
    promise.status = type
    promise.val = callbacks
      ? callbacks.reduce((val, f) => f[type] ? f[type](val) : val, result)
      : promise.val
    callbacks = null;
  }

  function resolve(result) {
    complete('resolve', result);
  }
  function reject(err) {
    complete('reject', err);
  }
  function then(resolve, reject) {
    if (promise.status === "pending") {
      callbacks.push({ resolve, reject });
    } else if (promise.status === "reject") {
      promise.val = reject ? reject(promise.val) : promise.val
    } else {
      promise.val = resolve ? resolve(promise.val) : promise.val
    }
    return promise
  }

  function finallyFun(finalFn) {
    return then(finalFn, finalFn);
  }

  function catchFun(failFn) {
    return then(null, failFn);
  }


  if (fork) {
    fork(resolve, reject)
  }
  return promise;
};

MyPromise.resolve = (p) => {
  if (p.then) {
    return p
  } else {
    return MyPromise((res) => {
      res(p)
    });
  }
}

MyPromise.reject = (p) => {
  if (p.then) {
    return p
  } else {
    return MyPromise((_, rej) => {
      rej(p)
    });
  }
}

MyPromise.all = (pList) => {
  return MyPromise((resolve, reject) => {
    const len = pList.length;
    let done = 0;
    let result = [];
    for (let i = 0; i < len; i++) {
      pList[i].then((val) => {
        done++;
        result[i] = val
        if (done === len) {
          resolve(result);
        }
      }, (err) => {
        reject(err);
      });
    }
  });
}

MyPromise.race = (pList) => {
  return MyPromise((resolve, reject) => {
    const len = pList.length;
    for (let i = 0; i < len; i++) {
      pList[i].then(val => {
        resolve(val);
      }, err => {
        reject(err);
      });
    }
  });
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment