Janji, berikan parameter tambahan ke rantai kemudian

100

Sebuah janji, misalnya:

var P = new Promise(function (resolve, reject) {
  var a = 5;
  if (a) {
    setTimeout(function(){
      resolve(a);
    }, 3000);
  } else {
    reject(a);
  }
});

Setelah kita panggil, barulah metode yang dijanjikan:

P.then(doWork('text'));

Fungsi doWork terlihat seperti ini:

function doWork(data) {
  return function(text) {
    // sample function to console log
    consoleToLog(data);
    consoleToLog(b);
  }
}

Bagaimana cara menghindari mengembalikan fungsi dalam di doWork, untuk mendapatkan akses ke data dari parameter teks dan janji? Adakah trik untuk menghindari fungsi batin?

pengguna3110667
sumber
1
Mengapa ada orang yang dengan sengaja menolak kari ? Untuk menggunakan bindmetode mengerikan ? - yang juga sangat lambat.
@ Untuk atau saya tidak mengerti Anda, dapatkah Anda memberikan beberapa kode untuk klarifikasi?
Roland

Jawaban:

86

Anda dapat menggunakan Function.prototype.binduntuk membuat fungsi baru dengan nilai yang diteruskan ke argumen pertamanya, seperti ini

P.then(doWork.bind(null, 'text'))

dan Anda dapat mengubah doWorkke,

function doWork(text, data) {
  consoleToLog(data);
}

Sekarang, textakan benar-benar 'text'masuk doWorkdan dataakan menjadi nilai yang diselesaikan oleh Janji.

Catatan: Pastikan Anda memasang penangan penolakan ke rantai janji Anda.


Program kerja: Salinan langsung di REPL Babel

function doWork(text, data) {
  console.log(text + data + text);
}

new Promise(function (resolve, reject) {
    var a = 5;
    if (a) {
      setTimeout(function () {
        resolve(a);
      }, 3000);
    } else {
      reject(a);
    }
  })
  .then(doWork.bind(null, 'text'))
  .catch(console.error);
thefourtheye
sumber
terima kasih, itu membantu, sebelumnya saya mencoba doWork.call (ini, 'teks'), tetapi data diganti dengan 'teks'
pengguna3110667
2
callmemanggil fungsi di tempat, bindmembuat fungsi baru, namun keduanya menerima konteks eksekusi sebagai argumen pertama mereka.
sdgluck
103

Mungkin jawaban yang paling mudah adalah:

P.then(function(data) { return doWork('text', data); });

Atau, karena ini diberi tag ecmascript-6, menggunakan fungsi panah:

P.then(data => doWork('text', data));

Menurut saya ini paling mudah dibaca, dan tidak terlalu banyak untuk ditulis.

jib
sumber
5

Gunakan kari.

var P = new Promise(function (resolve, reject) {
    var a = 5;
    if (a) {
        setTimeout(function(){
            resolve(a);
        }, 3000);
    } else {
        reject(a);
    }
});

var curriedDoWork = function(text) {
    return function(data) {
        console.log(data + text);
    }
};

P.then(curriedDoWork('text'))
.catch(
    //some error handling
);
yks
sumber
b berhati-hatilah dengan ini, jika Anda membuat curriedDoWorkjanji dengan melakukan return new Promise()di baris pertama fungsi ini, janji tersebut dijalankan segera setelah Anda memanggil curriedDoWork()(seperti yang Anda lakukan di..then(curriedDoWork('text'))
Flame
@Flame: jawaban singkat, demi kenyamanan Anda, Anda dapat menggabungkan janji ke dalam sebuah fungsi, jika Anda ingin melakukannya.
germain
@yks, Anda dapat menunjukkan sintaks ini yang cukup menarik const curriedWork = text => data => console.log (data + teks)
germain
1
@germain ah ya saya pernah melihat formulir ini sebelumnya, harus menyukai pemrograman fungsional. Namun saya mengalami fungsi panah rusak di beberapa browser, jadi saya cenderung menghindarinya sekarang.
yks
@yks, hanya Internet Explorer yang tidak mendukungnya dan tidak akan pernah, karena Edge, Internet Explorer yang terakhir dibangun adalah 9 Desember 2015. Mari kita lanjutkan ~
germain
0

Lodash menawarkan alternatif yang bagus untuk hal ini.

 P.then(_.bind(doWork, 'myArgString', _));

 //Say the promise was fulfilled with the string 'promiseResults'

 function doWork(text, data) {
     console.log(text + " foo " + data);
     //myArgString foo promiseResults
 }

Atau, jika Anda ingin fungsi sukses hanya memiliki satu parameter (hasil janji yang terpenuhi), Anda dapat menggunakannya dengan cara ini:

P.then(_.bind(doWork, {text: 'myArgString'}));

function doWork(data) {
    console.log(data + " foo " + this.text);
    //promiseResults foo myArgString
}

Ini akan melekat text: 'myArgString'pada thiskonteks di dalam fungsi.

JellyRaptor
sumber
0

Jawaban baru untuk pertanyaan ini adalah dengan menggunakan fungsi panah, yang secara otomatis mengikat 'ini' dan jauh lebih mudah dibaca. Google untuk tautan seperti: https://2ality.com/2016/02/arrow-functions-vs-bind.html

Anda bisa mengatur teks seperti ini: this.text = 'text' P. lalu (data => doWork (data)); //this.text di dalam doWork akan dievaluasi menjadi 'text'.

Ini disarankan oleh jib di atas dan bahwa (atau ini!) Harus menjadi jawaban yang diterima sekarang.

giwyni
sumber