最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Creating a promise without the new keyword - Stack Overflow

programmeradmin1浏览0评论

After watching fun fun function, I decided not to use the new keyword.

But here is a foundational example of how to use promises:

var promise = new Promise(function(resolve, reject) {
  // do a thing, possibly async, then…

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

Q: How do I create a promise without the use of the new keyword?

After watching fun fun function, I decided not to use the new keyword.

But here is a foundational example of how to use promises:

var promise = new Promise(function(resolve, reject) {
  // do a thing, possibly async, then…

  if (/* everything turned out fine */) {
    resolve("Stuff worked!");
  }
  else {
    reject(Error("It broke"));
  }
});

Q: How do I create a promise without the use of the new keyword?

Share Improve this question asked Sep 19, 2017 at 19:34 Phillip SennPhillip Senn 47.7k91 gold badges261 silver badges378 bronze badges 5
  • 1 Why have you decided not to use the new keyword? Did you watch and understand the video? You can follow the example in the video exactly... not sure what you are trying to acplish. – skyline3000 Commented Sep 19, 2017 at 19:44
  • 2 Promise is an object. If it so, it should be used with new for creation new examples of this object... – Sergey Commented Sep 19, 2017 at 19:55
  • 5 Don't trust every video you watch on YouTube. – robertklep Commented Sep 19, 2017 at 20:01
  • @Sergey, new does not create new examples of the Promise object. Promise is a constructor (a function). You create examples of Promise.prototype, not Promise. – trincot Commented Sep 20, 2017 at 7:57
  • 1 Seems like a pretty pointless objective to avoid the supported and well understood and simple way of creating a promise. – jfriend00 Commented Sep 20, 2017 at 22:08
Add a ment  | 

4 Answers 4

Reset to default 4

As a pure academic question, you could work around new by creating a thenable (for which you don't need new), and then you can convert that thenable to a full-blown promise with Promise.resolve:

function createPromise(executor) {
    let callback;
    function resolve(resolution, arg) {
        Promise.resolve().then(function () {
            callback[resolution](arg);
        });
    }
    try {
        executor(resolve.bind(null, "fulfill"), resolve.bind(null, "reject"));
    } catch(e) {
        resolve("reject", e);
    }
    return Promise.resolve({ 
        then: function (fulfill, reject) {
            callback = { fulfill, reject };
        }
    });
}

// Demo
var prom1 = createPromise(function (resolve, reject) {
    setTimeout(function () { resolve("Stuff worked!") }, 1000);
});
var prom2 = createPromise(function (resolve, reject) {
    setTimeout(function () { reject("It broke") }, 1000);
});

prom1.then(function (v) { console.log(v); });
prom2.catch(function (err) { console.log(err) });
console.log('waiting for promises to resolve');

Some have reasons to avoid the use of new, but if that has to lead to the above code, then clearly some exceptions should be allowed. Unless someone has a better idea to create promises without the use of new, one has to implement some Promise characteristics again (such as the try ... catch and the asynchronous call of the then callback) only to work around new. This seems a bad idea.

Conclusion: just use new for creating new promises.

Use async/await

const getPromise = async () => {
    // do a thing, possibly async, then…

    if (/* everything turned out fine */) {
        return 'Stuff worked!'
    } else {
        throw 'It broke'
    }
});
const promise = getPromise()

But please realize that you can't just call Error, calling constructor without new keyword throws garbage to global object in NodeJS (or to window object in browser JS). You have to use new Error. I hope I didn't create a whole new problem for you.

Also, note that async/await is just a syntactic sugar, the code will run with new anyway. Also, I suggest not to take advice literally. Granted, new is evil, but sometimes necessary in order not to over-plicate things.

MDN's Promise.resolve() and Promise.reject() man pages show how those functions return thenables.

The following code snippet goes a step further to show how they can be used to make myFunc wrap _myFunc to return a thenable.

'strict';

function _myFunc(tf){
  if (tf)
    return; 
  throw new Error('flubbed it');
}
function myFunc(tf){
  try { return Promise.resolve(_myFunc(tf));}
  catch(e) { return Promise.reject(e);}
}

function main() {
  try {
    _myFunc(false);
    console.log('SUCCESS');
  } catch (e) {
    console.log(`FAILED: ${e.message}`);
  }

  try {
    _myFunc(true);
    console.log('SUCCESS');
  } catch (e) {
    console.log(`FAILED: ${e.message}`);
  }

  myFunc(false)
    .then(()=>{ console.log('success'); })
    .catch((e)=>{ console.log(`failed: ${e.message}`); });

  myFunc(true)
    .then(()=>{ console.log('success'); })
    .catch((e)=>{ console.log(`failed: ${e.message}`); });

}

main();

However, because there are no promises, there is no await either, and we are back to the pyramid of doom when it es to synchronizing. As you can see in the output

FAILED: flubbed it
SUCCESS
success
failed: flubbed it

the order of last two results are out of order. That is because the JS interpreter sees the use of a thenable as an instruction to run the mand asynchronously.

In conclusion, the great thing about Promises is the ability to await and use Promise.all or Promise.race etc, which require Promises with state, for which new Promise(...) is obviously required.

You can use a wrapper function:

const Guarantee = function () {
  var _resolve = null
  var _reject = null

  var promise = new Promise(function (resolve, reject) {
    _resolve = resolve
    _reject = reject
  })

  promise.resolve = function () {
    _resolve.apply(promise, arguments)
  }

  promise.reject = function () {
    _resolve.apply(promise, arguments)
  }

  return promise
}

function doSomething () {
  const promise = Guarantee()

  setTimeout(function () {
    promise.resolve('123')
  }, 1000)

  return promise
}

doSomething()
  .then(function (data) {
    console.log(data)
  })
  • https://github./webarthur/node-guarantee
  • https://www.npmjs./package/node-guarantee

Enjoy!

发布评论

评论列表(0)

  1. 暂无评论