angular.js - Cara menulis panggilan berantai janji
高洛峰
高洛峰 2017-05-15 16:51:30
0
4
532

Sebagai contoh, saya mempunyai A.func1() yang tidak segerak dan ia boleh mengembalikan objek x1 Saya juga mempunyai B.func2() yang juga tidak segerak dan perlu dilaksanakan berdasarkan x1, dan kemudian B. .func2 mengembalikan nilai akhir t, dan beberapa paparan segera akan dilakukan berdasarkan nilai akhir ini. Bagaimana saya harus menulis ini?
Kod yang saya tulis sendiri adalah seperti ini

A.func1().
    then(function(x1) {
        B.func2(x1).
            then(function(t) {
                //do something
            })
    })

Tapi rasanya sama je kesannya sama ada guna dulu atau tidak...masih bertukar kembali menjadi piramid

高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

membalas semua(4)
世界只因有你

Sebagai tindak balas kepada komen tambahan dalam ulasan tentang "keadaan menyelamatkan semasa panggilan berterusan", saya ingin menghuraikan beberapa strategi

Strategi terbaik: Nyahpenyataan

Iaitu, laraskan logik anda supaya proses panggilan A.func1, B.func2, dan fungsi tanpa nama (sebut saja func3) tidak mengandungi keadaan, iaitu, biarkan func3 hanya bergantung pada output func2 , bukan output func1; atau biarkan func2 tidak bergantung pada func1, gunakan sesuatu seperti Promise.all untuk mendapatkan hasil func1 dan func2 pada masa yang sama dan buangnya ke func3

Strategi pusat: status penyelenggaraan berubah "global"

Kelebihan: negeri boleh dipanjangkan kepada keadaan.x2 .x3...
Masalah: Jika rantaian panggilan yang panjang mempunyai keadaan yang kompleks, ia adalah mudah untuk mencemari pepijat, dan kebolehselenggaraan kod akan dikurangkan dengan serius

js
function yourLogic() { var state = {}; return A.func1() .then(function(x1) { state.x1 = x1; return B.func2(x1); }) .then(function(t) { //play with t & state.x1 return yourResult; }); }
Kaedah bind

bluebird boleh mengikat Arg ini dan boleh digunakan untuk mengekalkan keadaan Prinsipnya adalah sama

js
function yourLogic() { return A.func1() .bind({})//新建空对象用于保留状态 .then(function(x1) { this.x1 = x1; return B.func2(x1); }) .then(function(t) { //play with t & this.x1 return yourResult; }); }

Strategi pertengahan: penghantaran tambahan sementara

Kelebihan: Tanpa keadaan, jika rantai panggilan panjang, keadaan tambahan ini dikawal antara dua langkah, mengekalkan kebolehselenggaraan yang lebih baik dan kurang terdedah kepada pepijat
Kelemahan: Jika setiap langkah rantai panggilan panjang mempunyai keadaan, ia akan menjadi sangat bertele-tele

js
function yourLogic() { return A.func1() .then(function(x1) { return B.func2(x1) .then(function(t) { return { t: t, x1: x1 } }); }) .then(function(state) { //play with state.t & state.x1 return yourResult; }); }

Sudah tentu, dalaman kemudian di sini juga boleh dikapsulkan dan dioptimumkan sendiri

js
function yourLogic() { return A.func1() .then(function(x1) { return keepState(B.func2(x1), { x1: x1 }, 't'); }) .then(function(state) { //play with state.t & state.x1 return yourResult; }); } function keepState(promise, state, key) { return promise.then(function(value) { state[key] = value; return state; }); }

Penyelesaian terakhir: Keadaan penyelenggaraan penutupan

Malah, ia adalah cara asal menulis soalan, saya rasa masalah utamanya ialah soalan itu telah diturunkan kembali kepada "neraka panggilan balik" yang asal atau memalukan piramid panggilan balik

Kelebihannya...berkesan

js
function yourLogic() { return A.func1() .then(function(x1) { return B.func2(x1) .then(function(t) { //play with t & x1 return yourResult; }); }) }
世界只因有你

Mengembalikan objek then terus di dalam Promise, seperti berikut:

javascript
A.func1() .then(function (x1) { return B.func2(x1); }) .then(function (t) { // do something });

Sebagai tindak balas kepada masalah yang dinyatakan dalam ulasan anda, jika anda tidak menggunakan pustaka Promise pihak ketiga, anda boleh menggunakannya seperti berikut:

javascriptvar promise = new Promise(function (resolve, reject) {
    var firstValue;
    A.func1()
        .then(function (x1) {
            firstValue = x1;    // 临时保存
            return B.func2(x1);
        }, reject)
        .then(function (x2) {
            resolve({
                firstValue: firstValue,
                secondValue: x2
            });
        }, reject);
});

promise.then(function (result) {
    console.log(result);    // {"firstValue": "Hello", "secondValue": "World"}
});

Menggunakan pustaka Promise pihak ketiga boleh memudahkan proses ini.

巴扎黑

Promise akan mengembalikan objek janji, supaya ia boleh menggunakan panggilan berantai yang elegan.

过去多啦不再A梦

Jika nilai pulangan fungsi pada masa itu ialah kuantiti langsung, ia akan digunakan sebagai parameter panggilan berantai seterusnya
Jika nilai pulangan mempunyai antara muka janji, hasil keputusan janji dikembalikan
Gunakan q sebagai contoh

var q = require('q');

var a = function(){
  var d = q.defer();

  d.resolve(1);
  return d.promise;
};

a().then(function(r){
  console.log(r); // 此处是1
  return 2;
}).then(function(r){
  console.log(r);  // 此处2,是由上一个then返回的
  var d = q.defer();
  d.resolve(3);
  return d.promise;
}).then(function(r){
  console.log(r); // 此处是3,由上一个then返回的promise的resolve提供.当需要异步调用时直接return的值肯定不够用,这时就需要返回promise对象.
});
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan