在没有new关键字的情况下创建承诺

时间:2017-09-19 19:34:46

标签: javascript promise

观看fun fun function后,我决定不使用new关键字。

但这是如何使用承诺的基本示例:

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"));
  }
});

问:如何在不使用new关键字的情况下创建承诺?

4 个答案:

答案 0 :(得分:2)

使用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()

但请注意,您不能只调用Error,调用没有new关键字的构造函数会将NodeJS(或global}对象中的window对象抛出在浏览器JS)。您必须使用new Error。我希望我没有为你创造一个全新的问题。

另外,请注意async/await只是一个语法糖,无论如何代码都会以new运行。另外,我建议不要从字面上理解。当然,new是邪恶的,但有时是必要的,以免过度复杂化。

答案 1 :(得分:2)

作为一个纯粹的学术问题,你可以通过创建一个(不需要new)来设置new,然后你可以转换它可以通过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');

有些人有理由避免使用new,但如果必须导致上述代码,那么显然应该允许一些例外。除非有人在不使用new的情况下更好地创建promises,否则必须再次实现一些Promise特性 (例如try ... catch异步< / em>调用then回调)只能解决new。这似乎是一个坏主意。

结论:只需使用new来创建新的承诺。

答案 2 :(得分:1)

MDN的Promise.resolve()Promise.reject() 手册页显示了这些函数如何返回then ables。

以下代码段进一步说明了如何使用它们来myFunc包装_myFunc以返回then可用。

'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();

但是,由于没有承诺,所以也没有await,并且在进行同步时我们回到pyramid of doom。 如您在输出中所见

FAILED: flubbed it
SUCCESS
success
failed: flubbed it

最后两个结果的顺序不正确。这是因为JS解释器认为可以使用then作为指令来异步运行命令。

总而言之,Promise的伟大之处在于能够await并使用Promise.allPromise.race等,这需要Promise的状态,显然需要new Promise(...)

答案 3 :(得分:0)

您可以使用包装函数:

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)
  })

享受!