Conjuring JQuery延迟了monadic咒语

受到这个 (优秀的)讨论在javascript中使用Promise的启发,我试图找出如何使用Deferred将异步和非异步函数链接在一起,以避免在使用我的“ 全局存储 ”代码时支付回调税。

我有几个与此相关的问题,但我会在这里一起问他们,因为背景是一样的。

我无法解决的一件事是我如何能够推断出非异步的东西 – 也就是说,如何获取值,将其包装在promise中并直接返回? ( a -> M

另外,我如何获取异步函数并将其包装,以便它直接返回结果,但包含在promise中? ( (a -> b) -> (a -> M)

最后一个问题,对于monadic怪胎 – 这个函数有一个标准名称吗? [a] -> (a -> M) -> M

将值包装到promise中就像使用$ .when一样简单:

 var promise = $.when( value ); 

此外,从jQuery 1.6开始,你有一个非常简单的链接方法(管道):

 var chained = functionThatReturnsAPromise().pipe(function( resolveValue ) { return functionThatReturnsAnotherPromise( resolveValue ); }); chained.done(function() { // Both asynchronous operations done in sequence }); 

希望这可以帮助。

认为你将价值转化为承诺的方式就是“预先成功”延期:

 function v2p(value) { var rv = $.Deferred(); rv.resolveWith(null, [value]); return rv.promise(); } 

现在将函数传递给“.do​​ne()”将导致函数立即被调用该值。

 v2p("hello").done(function(value) { alert(value); }); 

会马上警告“你好”。

在@Pointy的帮助下,实施“升降机”变得微不足道:

 function unit(value) { var rv = $.Deferred(); rv.resolveWith(null, [value]); return rv.promise(); } function lift(fn) { return function(x) { return unit(fn(x)); }; } lift(alert)("hello"); function bind(fn) { return function(x) { return x.done(function(y) { return fn(y); }); } } function compose(f, g) { return function(x) { g(f(x)); } }; function twice(x) { return 2 * x; } var alert2 = compose(bind(lift(twice)), bind(lift(alert))); alert2(unit(4)); //error at the end because alert doesn't return any values 

现在我只需要弄清楚如何实现[a] -> (a -> M) -> M<[b]> ,以及它的名称!

编辑 ,我最终实现(a -> M) -> ([a] -> M<[b]>) ,它看起来像这样:

 function listBind(fn) { return function(a) { var Mb = $.Deferred(); var b = [], pending = a.length; var callback = function(i,val) { b[i] = val; if(--pending == 0) Mb.resolve(b); }; for(var i = 0, n = a.length; i < n; i++) { (function(closure) { //ugly, but have to use closure to 'copy' i fn(a[closure]).done(function(val) { callback(closure, val); }) })(i); } return Mb.promise(); }; } 

因此,给定一个获取一个延迟项的函数,此函数listBind返回一个新函数,该函数接受一个值数组,并使用它们返回延迟项内的另一个值列表。