ES6諾言
ES6承諾是有限狀態機,並因此需要複雜的實現。除此之外無極/ A +規格配備了很多粗糙的邊緣:Promises優於CPS和Continuation Functor/Monad有什麼優勢?
- 重載
then
(地圖/鏈) - 遞歸平坦化/當時能夠同化
- 自動升降
- 幾個用戶(多播)
- 急於評價
組播分發和渴望的評價是除其他外ES6承諾無法取消的原因。另外,我們不能添加我們自己的具有特定功能的圖層,因爲它們通過遞歸拼合立即被同化。
我很確定這些設計決定有很多很好的理由。然而,現在我們擁有一個不變的核心語言特性,而不是具體的競爭DSL用於用戶空間中的異步控制流。當然,互操作非常重要,但是在不考慮整個語言的後向兼容性的情況下,發展異步控制流功能的能力也是非常重要的。
延續傳遞風格
延續傳遞風格摘要從異步控制流,因爲它擺脫了return
聲明。要重新組合性,我們只需要延續的背景下,函子:
const compk = (f, g) => x => k => f(x) (x => g(x) (k));
const inck = x => k => setTimeout(k, 0, x + 1);
const log = prefix => x => console.log(prefix, x);
compk(inck, inck) (0) (log("async composition:")); // 2
當然,我們要組成兩個以上的功能。代替手動編寫compk3 = (f, g, h) => x => k => f(x) (x => g(x) (y => h(y) (k)))
等,一個編程解決方案需要:
const compkn = (...fs) => k =>
fs.reduceRight((chain, f) => x => f(x) (chain), k);
const inck = x => (res, rej) => setTimeout(res, 0, x + 1);
const log = prefix => x => console.log(prefix, x);
compkn(inck, inck, inck) (log("async composing n functions:")) (0); // 3
這種方法完全缺乏異常處理。讓我們天真地適應常見的回調格局:
const compk = (f, g) => x => (res, rej) =>
f(x) (x => g(x) (res), x => rej(x));
const compkn = (...fs) => (res, rej) =>
fs.reduceRight((chain, f) => x => f(x) (chain, x => rej(x)), res);
const inc = x => x + 1;
const lift = f => x => k => k(f(x));
const inck = x => (res, rej) => setTimeout(res, 0, x + 1);
const decUIntk = x => (res, rej) =>
setTimeout(x => x < 0 ? rej("out of range " + x) : res(x), 0, x - 1);
const log = prefix => x => console.log(prefix, x);
compk(decUIntk, inck) (0)
(log("resolved with:"), log("rejected with:")); // rejected
compkn(inck, decUIntk, inck)
(log("resolved with:"), log("rejected with:")) (0); // resolved
這只是一個小品 - 很多的努力將不得不投入,實現了妥善的解決辦法。但這是我猜想的一個概念證明。 compk
/compkn
是非常簡單的,因爲他們不必對抗狀態。
那麼複雜的ES6承諾相對於延續傳遞函數和相應的DSL(如continuation functor/monad)有什麼優勢?
一個好處就是許諾相當接近於同步程序的風格,大多數人都習慣了,而你有上面的東西看起來完全陌生的人缺乏FP相當廣泛的背景。例如,我不知道你的例子是否包含一個人們想異步執行的事例。我只看到一堆以陌生方式使用的奇怪命名的函數。它看起來像你試圖解釋CFP,但你的方式,將毫無意義的人是不熟悉的人這樣做。 – JLRishe
另外,我認爲這是不正確的:「此外,我們不能添加當時ABLES具有特定功能的我們自己的層,因爲它們立即被遞歸壓扁同化」 _ _這是完全可以保證的承諾你在您的代碼中使用包裹在您的諾言中,以利用額外功能(如藍鳥中的功能)。 – JLRishe
'then'函數實際上是組合的。它返回一個新的承諾,並承諾連鎖如果回調是一個承諾本身並立即解決,如果它返回一個值或拋出一個異常/拒絕。這使得代碼更平坦,你確實可以使promiseCompose,要麼傳說中的承諾,構成'then'在鏈或者是返回,將調用將產生最初的承諾,然後做同樣的鏈接初始函數的函數。國際海事組織除了額外的工具外,它與CPS非常相似,因此我們不必製作不斷創造新承諾的代碼。 – Sylwester