Perbincangan terperinci tentang nodejs asynchronous programming_node.js

WBOY
Lepaskan: 2016-05-16 16:29:19
asal
1473 orang telah melayarinya

Keperluan semasa melibatkan sejumlah besar operasi tak segerak dan halaman sebenar semakin condong ke arah aplikasi satu halaman. Pada masa hadapan, anda boleh menggunakan rangka kerja tulang belakang, sudut, kalah mati dan lain-lain, tetapi isu tentang pengaturcaraan tak segerak adalah isu pertama yang perlu dihadapi. Dengan kebangkitan nod, pengaturcaraan tak segerak telah menjadi topik yang sangat hangat. Selepas tempoh kajian dan latihan, beberapa butiran pengaturcaraan tak segerak diringkaskan.

1. Klasifikasi pengaturcaraan tak segerak

Kaedah untuk menyelesaikan masalah tak segerak secara amnya termasuk: panggil balik terus, mod pub/sub (mod acara), pustaka kawalan perpustakaan tak segerak (seperti tak segerak, bila), janji, Penjana, dsb.
1.1 Fungsi panggil balik

Fungsi panggil balik ialah kaedah yang biasa digunakan untuk menyelesaikan masalah tak segerak Ia sering dihubungi dan digunakan, mudah difahami dan sangat mudah untuk dilaksanakan dalam perpustakaan atau fungsi. Ini juga merupakan kaedah yang sering digunakan oleh semua orang apabila menggunakan pengaturcaraan tak segerak.

Tetapi kaedah fungsi panggil balik mempunyai masalah berikut:

1. Ia mungkin membentuk piramid bersarang jahat dan kodnya sukar dibaca

2. Hanya boleh sepadan dengan satu fungsi panggil balik, yang menjadi had dalam banyak senario.

1.2 mod pub/sub (acara)

Mod ini juga dipanggil mod acara, iaitu acara fungsi panggil balik Ia sangat biasa dalam perpustakaan seperti jQuery.

Model pelanggan penerbitan acara itu sendiri tidak mempunyai masalah panggilan segerak dan tak segerak, tetapi dalam nod, panggilan memancarkan kebanyakannya dicetuskan secara tak segerak dengan gelung acara. Mod ini sering digunakan untuk memisahkan logik perniagaan Penerbit acara tidak perlu memberi perhatian kepada fungsi panggil balik yang didaftarkan, mahupun bilangan fungsi panggil balik Data boleh dipindahkan secara fleksibel melalui mesej.

Kelebihan mod ini ialah: 1. Mudah difahami 2. Tidak lagi terhad kepada satu fungsi panggil balik.

Kelemahan: 1. Perlu menggunakan perpustakaan kelas; 2. Susunan acara dan fungsi panggil balik adalah sangat penting

Salin kod Kod adalah seperti berikut:

var img = document.querySelect(#id);
img.addEventListener('load', function() {
// Pemuatan imej selesai
 …
});
img.addEventListener('error', function() {
// Sesuatu telah berlaku
……
});

Terdapat dua masalah dengan kod di atas:

a. Img sebenarnya telah dimuatkan, dan fungsi panggil balik muat hanya terikat pada masa ini, akibatnya, panggilan balik tidak akan dilaksanakan, tetapi kami masih berharap untuk melaksanakan fungsi panggil balik yang sepadan.

Salin kod Kod adalah seperti berikut:

var img = document.querySelect(#id);
beban fungsi() {
...
}
if(img.complete) {
muat();
} lain {
img.addEventListener('muat', muat);
}
img.addEventListener('error', function() {
// Sesuatu telah berlaku
……
});

b. Tidak dapat mengendalikan pengecualian dengan baik

Kesimpulan: Mekanisme acara paling sesuai untuk mengendalikan perkara yang berlaku berulang kali pada objek yang sama Tidak perlu mempertimbangkan kejadian sebelum fungsi panggil balik terikat.

1.3 Pustaka kawalan tak segerak

Pustaka tak segerak semasa terutamanya termasuk Q, when.js, win.js, RSVP.js, dsb.

Ciri perpustakaan ini ialah kodnya adalah linear dan boleh ditulis dari atas ke bawah, yang selaras dengan tabiat semula jadi.

Kelemahannya ialah gaya berbeza, yang menyukarkan membaca dan meningkatkan kos pembelajaran.

1.4 Janji

Janji diterjemahkan ke dalam bahasa Cina sebagai janji Pemahaman peribadi saya ialah selepas penyiapan tidak segerak, ia akan memberikan hasil luaran (berjaya atau gagal), dan berjanji bahawa hasilnya tidak akan berubah. Dalam erti kata lain, Janji mencerminkan nilai pulangan akhirnya bagi operasi (Janji mewakili nilai akhirnya yang dikembalikan daripada penyiapan tunggal operasi). Pada masa ini, Promise telah diperkenalkan ke dalam spesifikasi ES6, dan penyemak imbas lanjutan seperti Chrome dan Firefox telah melaksanakan kaedah asli ini secara dalaman, yang sangat mudah digunakan.

Mari analisa ciri-ciri Janji dari aspek berikut:

1.4.1 Status

Mengandungi tiga keadaan: belum selesai, dipenuhi dan ditolak Hanya dua peralihan boleh berlaku antara tiga keadaan (daripada belum selesai--->dipenuhi, belum selesai-->ditolak), dan peralihan keadaan hanya boleh berlaku sekali.

1.4.2 kemudian kaedah

Kaedah kemudian digunakan untuk menentukan fungsi panggil balik selepas acara tak segerak selesai.

Kaedah ini boleh dikatakan kaedah jiwa Janji, yang menjadikan Janji penuh dengan sihir. Terdapat beberapa manifestasi khusus seperti berikut:

a) Kaedah kemudian mengembalikan Janji. Ini membolehkan operasi bersiri berbilang operasi tak segerak.

Mengenai pemprosesan nilai dalam bulatan kuning 1 dalam gambar di atas, ia adalah bahagian Janji yang lebih rumit Pemprosesan nilai terbahagi kepada dua situasi: Objek Janji dan objek bukan Janji.

Apabila nilai bukan jenis Janji, hanya gunakan nilai sebagai nilai parameter janji Janji kedua; apabila ia adalah jenis Janji, status dan parameter janji2 ditentukan sepenuhnya oleh nilai promsie2 benar-benar boneka nilai, promise2 hanyalah jambatan yang menghubungkan yang tidak segerak yang berbeza.

Salin kod Kod adalah seperti berikut:

Promise.prototype.then = function(onFulfilled, onRejected) {
    kembalikan Janji baharu(fungsi(selesaikan, tolak) {           //此处的Promise标注为promise2
        pemegang ({
            onFulfilled: onFulfilled,
            onRejected: onRejected,
            azam: azam,
            menolak: menolak
        })
    });
}
pemegang fungsi(ditunda) {
    var handleFn;
    if(nyatakan === 'dipenuhi') {
        handleFn = tertunda.onFulfilled;
    } else if(nyatakan === 'ditolak') {
        handleFn = deferred.onRejected;
    }
    var ret = handleFn(nilai);
    deferred.resolve(ret);                           //注意,此时的resolve是promise2的resolve
}
fungsi  menyelesaikan(val) {
    if(val && typeof val.then === 'fungsi') {
        val.then(menyelesaikan);                           // if val为promise对象或类promise对象时,promise2的状态完全由val决定
        kembali;
    }
    if(panggilan balik) {                                     // panggil balik为指定的回调函数
        panggil balik(val);
    }
}

  b)实现了多个不同异步库之间的转换。

    在异步中存在一个叫thenable的对象,就是指具有then方法的对象,只要一个对象个对象对就可以对其进行转换,例如:

复制代码 代码如下:

var tertunda = $('aa.ajax');      // !!ditunda.kemudian  === benar
var P = Promise.resolve(tertunda);
p.kemudian(......)

1.4.3 commonJS Promise/A规范

      目前关于Promise的规范存在Promise/A和Promise/A 规范,这说明关于Promise的实现是挺复来的。

复制代码 代码如下:
kemudian(fulfilledHandler, rejectedHandler, progressHandler)

1.4.4 注意事项

     一个Promise里面的回调函数是共享value的,在结果处理中value作为参数传递给出的nilai的,在结果处理中value作为参数传递给囸国家e是对象,那就要小心不要轻易修改value的值。

复制代码 代码如下:
var p = Promise.resolve({x: 1});
p.then(function(val) {
    console.log('panggilan balik pertama: ' val.x );
});
p.then(function(val) {
    console.log('panggilan balik kedua: ' val.x)
})
// panggil balik pertama: 1
// panggil balik kedua: 2

Penjana 1.5

Semua kaedah di atas adalah berdasarkan fungsi panggil balik untuk menyelesaikan operasi tak segerak Mereka tidak lebih daripada pengkapsulan fungsi panggil balik. Penjana dicadangkan dalam ES6, yang menambah cara untuk menyelesaikan operasi tak segerak dan tidak lagi bergantung pada fungsi panggil balik.

Ciri terbesar Generator ialah ia boleh menjeda dan memulakan semula fungsi. Ciri ini sangat membantu untuk menyelesaikan operasi tak segerak. Menggabungkan jeda Generator dengan pengendalian pengecualian janji boleh menyelesaikan masalah pengaturcaraan tak segerak dengan lebih elegan. Rujukan pelaksanaan khusus: Kyle Simpson

2. Masalah dengan pengaturcaraan tak segerak

2.1 Pengendalian pengecualian

a) Peristiwa tak segerak termasuk dua pautan: mengeluarkan permintaan tak segerak dan pemprosesan hasil Kedua-dua pautan ini disambungkan melalui gelung peristiwa. Kemudian apabila cuba tangkap digunakan untuk menangkap pengecualian, ia perlu ditangkap secara berasingan.

Salin kod Kod adalah seperti berikut:

cuba {
asyncEvent(panggilan balik); } tangkap(err) {
 …
}

Kod di atas tidak boleh menangkap pengecualian dalam panggilan balik, tetapi hanya boleh mendapatkan pengecualian dalam proses permintaan. Ini menimbulkan masalah: Jika pengeluaran permintaan dan pemprosesan permintaan diselesaikan oleh dua orang, adakah masalah akan timbul semasa mengendalikan pengecualian?

b) Promise melaksanakan penghantaran pengecualian, yang membawa beberapa faedah dan memastikan kod itu tidak disekat dalam projek sebenar. Tetapi jika terdapat banyak peristiwa tak segerak, tidak mudah untuk mengetahui peristiwa tak segerak yang menyebabkan pengecualian.

Salin kod Kod adalah seperti berikut:
// Penerangan senario: Paparkan maklumat penggera harga dalam CRM, termasuk maklumat pertandingan. Walau bagaimanapun, ia mengambil masa yang lama untuk mendapatkan maklumat pertandingan Untuk mengelakkan pertanyaan yang perlahan, bahagian belakang membahagikan rekod kepada dua bahagian dan memperolehnya secara berasingan.
// Langkah pertama: Dapatkan maklumat penggera harga, sebagai tambahan kepada maklumat persaingan
fungsi getPriceAlarmData() {
Kembalikan Janji baharu(fungsi(selesai) {
Y.io(url, {
Kaedah: 'dapat',
               data: params,
pada: function() {
Kejayaan: fungsi(id, data) {
selesaikan(alarmData);
                }
            }
});
});
}
// Selepas mendapat maklumat penggera, dapatkan maklumat pertandingan
getPriceAlarmData().then(function(data) {
//Penyampaian data, kecuali untuk maklumat pertandingan
render(data);
Kembalikan Janji baharu(fungsi(selesai) {
Y.io(url, {
Kaedah: 'dapat',
              data: {alarmList: data},
pada: function() {
Kejayaan: function(id, compData) {
                        selesaikan (compData);
                }
            }
});
});
}) // Selepas memperoleh semua data, berikan maklumat pertandingan
.then(fungsi(data) {
// Berikan maklumat pertandingan
render(data)
}, fungsi(err) {
//Pengendalian pengecualian
console.log(err);
});

Anda boleh menukar kod di atas kepada yang berikut:

Salin kod Kod adalah seperti berikut:

cuba{
// Dapatkan maklumat penggera selain daripada persaingan
var alarmData = alarmDataExceptCompare();
render(alarmData);
// Tanya maklumat pertandingan berdasarkan maklumat penggera
var compareData = getCompareInfo(alarmData);
render(compareData);
} tangkap(err) {
console.log(err.message);
}

Dalam contoh di atas, pengendalian pengecualian diletakkan pada penghujung, supaya apabila pengecualian berlaku dalam pautan tertentu, kami tidak dapat mengetahui dengan tepat peristiwa yang menyebabkannya.       

2.2 Masalah dengan jQuery.Deferred

Operasi tak segerak juga dilaksanakan dalam jQuery, tetapi pelaksanaannya tidak mematuhi spesifikasi janji/A, terutamanya dalam aspek berikut:

a. Bilangan parameter: Standard Promise hanya boleh menerima satu parameter, manakala jQuery boleh melepasi berbilang parameter

Salin kod Kod adalah seperti berikut:

fungsi asyncInJQuery() {
var d = new $.Deferred();
setTimeout(function() {
        d.resolve(1, 2);
}, 100);
Kembalikan d.janji()
}
asyncInJQuery().then(function(val1, val2) {
console.log('output: ', val1, val2);
});
// output: 1 2

b. Mengendalikan pengecualian dalam pemprosesan hasil

Salin kod Kod adalah seperti berikut:

fungsi asyncInPromise() {
Kembalikan Janji baharu(fungsi(selesai) {
​​ setTimeout(function() {
          var jsonStr = '{"name": "mt}';
            menyelesaikan(jsonStr);
}, 100);
});
}
asyncInPromise().then(function(val) {
var d = JSON.parse(val);
console.log(d.name);
}).then(null, function(err) {
console.log('tunjuk ralat: ' err.message);
});
// tunjukkan ralat: Penghujung input yang tidak dijangka
fungsi asyncInJQuery() {
var d = new $.Deferred();
setTimeout(function() {
        var jsonStr = '{"name": "mt}';
         d.resolve(jsonStr);
}, 100);
Kembalikan d.janji()
}
asyncInJQuery().then(function(val) {
var d = JSON.parse(val);
console.log(d.name);
}).kemudian(fungsi(v) {
console.log('success: ', v.name);
}, fungsi(err){
console.log('tunjuk ralat: ' err.message);
});
//Uncaught SyntaxError: Penghujung input yang tidak dijangka

Dari sini dapat dilihat bahawa Promise melakukan pemprosesan hasil pada fungsi panggil balik dan boleh menangkap pengecualian semasa pelaksanaan fungsi panggil balik, tetapi jQuery.Deferred tidak boleh.

Label berkaitan:
sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan