Pertanyaan Conjuring JQuery Ditangguhkan dengan mantra monadik


Terinspirasi oleh ini (Sangat bagus) diskusi tentang menggunakan Janji dalam javascript, saya mencoba mencari tahu bagaimana saya bisa menggunakan Ditangguhkan untuk menggabungkan fungsi asinkron dan non-asinkron, untuk menghindari membayar pajak panggilan balik ketika menggunakan 'Penyimpanan global'kode.

Saya punya beberapa pertanyaan yang berkaitan dengan ini, tetapi saya akan menanyakannya bersama-sama di sini, karena konteksnya sama.

Satu hal yang tidak dapat saya kerjakan adalah bagaimana saya dapat menunda sesuatu yang tidak sinkron - yaitu, bagaimana saya mengambil nilai, membungkusnya dalam sebuah janji, dan mengembalikannya secara langsung? (a -> M<a>)

Juga, bagaimana saya bisa mengambil fungsi asynchronous dan membungkusnya sehingga mengembalikan hasilnya secara langsung, tetapi dibungkus dalam sebuah janji? ((a -> b) -> (a -> M<b>))

Pertanyaan terakhir, untuk orang asing monadik - apakah ada nama standar untuk fungsi ini? [a] -> (a -> M<b>) -> M<[b]>


5
2018-04-06 16:27


asal


Jawaban:


Membungkus nilai ke dalam janji adalah sesederhana menggunakan $ .when:

var promise = $.when( value );

Juga, pada jQuery 1.6, Anda memiliki metode chaining (pipa) yang sangat sederhana:

var chained = functionThatReturnsAPromise().pipe(function( resolveValue ) {
        return functionThatReturnsAnotherPromise( resolveValue );
    });

chained.done(function() {
    // Both asynchronous operations done in sequence
});

Semoga ini membantu.


5
2017-08-23 00:53



saya berpikir cara Anda mengubah nilai menjadi Janji adalah hanya "pra-berhasil" yang Ditangguhkan:

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

Sekarang meneruskan fungsi ke ".done ()" akan menghasilkan fungsi yang segera dipanggil dengan nilai.

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

akan segera mengingatkan "halo".


1
2018-04-06 16:45



Dibantu oleh @Pointy, menerapkan 'lift' menjadi sepele:

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

Sekarang saya harus mencari tahu cara menerapkannya [a] -> (a -> M<b>) -> M<[b]>, dan apa namanya itu!

EDIT, Saya akhirnya menerapkan (a -> M<b>) -> ([a] -> M<[b]>) sebaliknya, tampilannya seperti ini:

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

Jadi, diberi fungsi yang mendapat satu item yang ditangguhkan, daftar fungsi iniBalik mengembalikan fungsi baru yang menerima larik nilai, dan menggunakannya untuk mengembalikan daftar nilai lain di dalam item yang ditangguhkan.


1
2018-04-06 17:23