[英]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 ... catch
和then
回調的異步調用)才能解決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
的使用視為異步運行命令的指令。
總之, Promise
的Promise.all
在於能夠await
和使用Promise.all
或Promise.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.