Rumah > Soal Jawab > teks badan
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
世界只因有你2017-05-15 16:53:30
Sebagai tindak balas kepada komen tambahan dalam ulasan tentang "keadaan menyelamatkan semasa panggilan berterusan", saya ingin menghuraikan beberapa strategi
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
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
Kaedah bindjs
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; }); }
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; }); }
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; }); }
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; }); }) }
世界只因有你2017-05-15 16:53:30
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:
javascript
var 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.
巴扎黑2017-05-15 16:53:30
Promise akan mengembalikan objek janji, supaya ia boleh menggunakan panggilan berantai yang elegan.
过去多啦不再A梦2017-05-15 16:53:30
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对象.
});