簡體   English   中英

創建沒有 new 關鍵字的承諾

[英]Creating a promise without the new keyword

看了fun fun 函數之后,我決定不使用new關鍵字了。

但這里有一個關於如何使用 Promise 的基本示例:

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關鍵字的情況下創建承諾?

使用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對象(或瀏覽器 JS 中的window對象)拋出垃圾。 你必須使用new Error 我希望我沒有給你制造一個全新的問題。

另外,請注意async/await只是一個語法糖,代碼無論如何都會以new運行。 另外,我建議不要從字面上接受建議。 誠然, new是邪惡的,但有時是必要的,以免使事情過於復雜。

作為一個純粹的學術問題,你可以解決new創建一個thenable(您不需要new ),然后你可以說thenable轉換成一個完整的成熟的承諾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情況下創建 Promise ,否則必須再次實現一些 Promise 特性(例如try ... catchthen回調的異步調用)才能解決new 這似乎是個壞主意。

結論:只需使用new來創建新的承諾。

MDN 的Promise.resolve()Promise.reject()手冊頁展示了這些函數如何返回then

下面的代碼片段更進一步展示了如何使用它們使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 ,當談到同步時,我們又回到了厄運金字塔 正如你在輸出中看到的

FAILED: flubbed it
SUCCESS
success
failed: flubbed it

最后兩個結果的順序是亂序的。 那是因為 JS 解釋器將then的使用視為異步運行命令的指令。

總之, PromisePromise.all在於能夠await和使用Promise.allPromise.race等,這需要Promise具有狀態,顯然需要new Promise(...)

您可以使用包裝函數:

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

享受!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM