Eski atasözü, iş için doğru aracı seçmeniz gerektiğidir. ES6 vaatleri temel sağlar. İstediğiniz veya ihtiyacınız olan tek şey temel bilgilerse, bu sizin için iyi çalışabilir / işe yarayabilir. Ancak, araç bölmesinde temellerden daha fazla araç vardır ve bu ek araçların çok yararlı olduğu durumlar vardır. Ve ES6 vaatlerinin hemen hemen her node.js projesinde yararlı olan promisifikasyon gibi bazı temel unsurları bile eksik olduğunu iddia ediyorum.
Bluebird söz kütüphanesine en çok alışkınım, bu yüzden çoğunlukla bu kütüphaneyle ilgili deneyimimden bahsedeceğim.
İşte, daha yetenekli bir Promise kütüphanesi kullanmak için en iyi 6 nedenim
Promisified async arabirimleri - .promisify()
ve .promisifyAll()
hala düz geri çağrılar gerektiren ve henüz vaatleri geri vermeyen tüm asenkron arabirimleri işlemek için inanılmaz derecede faydalıdır - bir kod satırı tüm arabirimin vaat edilmiş bir sürümünü oluşturur.
Daha Hızlı - Bluebird, çoğu ortamda yerel vaatlerden önemli ölçüde daha hızlıdır .
Eşzamansız dizi yinelemesini sıralama - Promise.mapSeries()
veya Promise.reduce()
her bir öğe üzerinde bir eşzamansız işlem çağırmak, ancak eşzamanlı olmayan işlemleri birbiri ardına gerçekleşecek şekilde sıralamak, aynı anda değil, bir dizi üzerinden yinelemenize izin vermek. Bunu hedef sunucu gerektirdiğinden veya bir sonucu diğerine iletmeniz gerektiğinden yapabilirsiniz.
Çoklu Dolgu - Tarayıcı istemcilerinin eski sürümlerinde vaatler kullanmak istiyorsanız, yine de bir çoklu dolguya ihtiyacınız olacaktır. Yeterli bir çoklu dolgu da alabilir. Node.js'nin ES6 vaatleri olduğundan, node.js'de bir çoklu dolguya ihtiyacınız yoktur, ancak bir tarayıcıda olabilir. Hem node.js sunucusunu hem de istemciyi kodluyorsanız, her ikisinde de aynı söz kitaplığına ve özelliklere sahip olmak çok yararlı olabilir (kodu paylaşmak daha kolay, ortamlar arasında bağlam geçişi yapmak, eşzamansız kod için ortak kodlama tekniklerini kullanmak vb. .).
Diğer Kullanışlı Özellikler - Bluebird vardır Promise.map()
, Promise.some()
, Promise.any()
, Promise.filter()
, Promise.each()
ve Promise.props()
hepsinden bazen kullanışlıdır. Bu işlemler ES6 vaatleri ve ek kodlarla gerçekleştirilebilirken, Bluebird önceden oluşturulmuş ve önceden test edilmiş bu işlemlerle birlikte gelir, böylece bunları kullanmak daha basit ve daha az koddur.
Yerleşik Uyarılar ve Tam Yığın İzleri - Bluebird, muhtemelen yanlış kod veya hata olan sorunlara karşı sizi uyaran bir dizi yerleşik uyarıya sahiptir. Örneğin, söz .then()
konusu sözü vermeden (geçerli vaat zincirine bağlamak için) bir işleyici içinde yeni bir vaat yaratan bir işlevi çağırırsanız , çoğu durumda, bu yanlışlıkla bir hatadır ve Bluebird size bu konuda bir uyarı verecektir. etki. Diğer yerleşik Bluebird uyarıları burada açıklanmaktadır .
İşte bu çeşitli konular hakkında biraz daha ayrıntı:
PromisifyAll
Herhangi bir node.js projesinde, hemen her yerde Bluebird kullanıyorum çünkü .promisifyAll()
modül gibi standart node.js modüllerinde çok şey kullanıyorum fs
.
Node.js, fs
modül gibi zaman uyumsuz GÇ yapan yerleşik modüllere bir söz arabirimi sağlamaz . Yani, bu arayüzlerle vaatler kullanmak istiyorsanız, ya kullandığınız her modül fonksiyonunun etrafına bir vaat sarmalayıcıyı elle kodlamaya ya da sizin için yapabilen ya da vaat kullanamayan bir kütüphane elde etmeye bırakılırsınız.
Bluebird's Promise.promisify()
ve Promise.promisifyAll()
vaatleri döndürmek için node.js çağrı kural asenkron API'lerin otomatik olarak kaydırılmasını sağlar. Son derece kullanışlı ve zaman tasarrufu. Her zaman kullanıyorum.
Bunun nasıl çalıştığına dair bir örnek:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
Alternatif olarak fs
, kullanmak istediğiniz her API için kendi söz paketinizi manuel olarak oluşturmak olabilir :
const fs = require('fs');
function readFileAsync(file, options) {
return new Promise(function(resolve, reject) {
fs.readFile(file, options, function(err, data) {
if (err) {
reject(err);
} else {
resolve(data);
}
});
});
}
readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
Ve bunu kullanmak istediğiniz her API işlevi için manuel olarak yapmanız gerekir. Bu açıkça bir anlam ifade etmiyor. Kaynak plakası kodu. Bu işi sizin için yapan bir yardımcı program da alabilirsiniz. Bluebird's Promise.promisify()
ve Promise.promisifyAll()
böyle bir yardımcı programdır.
Diğer Faydalı Özellikler
İşte özellikle yararlı bulduğum Bluebird özelliklerinden bazıları (bunların kod veya hız gelişimini nasıl kaydedebileceği konusunda birkaç kod örneği vardır):
Promise.promisify()
Promise.promisifyAll()
Promise.map()
Promise.reduce()
Promise.mapSeries()
Promise.delay()
Yararlı işlevine ek olarak, Promise.map()
aynı anda kaç işlemin çalışmasına izin verilmesi gerektiğini belirtmenize izin veren bir eşzamanlılık seçeneğini de destekler; kaynak.
Bunlardan bazıları hem bağımsız olarak adlandırılabilir hem de kendisinin çok fazla kod kaydedebilen bir yinelenebilir duruma karar verdiği bir vaatte kullanılabilir.
polyfill
Bir tarayıcı projesinde, Promise desteği olmayan bazı tarayıcıları hala desteklemek istediğiniz için, yine de bir çoklu dolguya ihtiyacınız vardır. Ayrıca jQuery kullanıyorsanız, bazen jQuery'de yerleşik olarak verilen söz desteğini kullanabilirsiniz (bazı durumlarda acı verici bir şekilde standart olmasa da, belki de jQuery 3.0'da sabittir), ancak proje herhangi bir önemli asenkron aktivitesi içeriyorsa, Bluebird genişletilmiş özellikleri çok yararlı.
Daha hızlı
Ayrıca Bluebird'in vaatlerinin V8'de vaat edilenlerden daha hızlı göründüğünü de belirtmek gerekir. Bkz Bu yayını o konu hakkında daha fazla tartışma için.
Bir Büyük Şey Node.js Eksik
Bludeird'i node.js geliştirmesinde daha az kullanmayı düşünmeme neden olan şey, node.js bir promisify işlevinde yerleşik olsaydı, böylece böyle bir şey yapabilirsiniz:
const fs = requirep('fs');
fs.readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
Veya yerleşik modüllerin bir parçası olarak zaten vaat edilmiş yöntemleri sunun.
O zamana kadar bunu Bluebird ile yapıyorum:
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
fs.readFileAsync('somefile.text').then(function(data) {
// do something with data here
});
ES6'nın node.js'de yerleşik destek sözü vermesi ve yerleşik modüllerin hiçbirinin söz vermediği biraz garip görünüyor. Bunun node.js'de çözülmesi gerekir. O zamana kadar tüm kütüphaneleri vaat etmek için Bluebird kullanıyorum. Yani, yerleşik modüllerin hiçbiri, ilk önce onları elle sarmadan onlarla vaatler kullanmanıza izin vermediğinden, vaatlerin node.js'de yaklaşık% 20 uygulandığını hissediyor.
Örnekler
Bluebird'in vaat ettiği ve Promise.map()
bir dizi dosyayı paralel olarak okuduğu ve tüm verilerle işiniz bittiğinde bildiren düz Sözler'e bir örnek :
Düz Sözler
const files = ["file1.txt", "fileA.txt", "fileB.txt"];
const fs = require('fs');
// make promise version of fs.readFile()
function fsReadFileP(file, options) {
return new Promise(function(resolve, reject) {
fs.readFile(file, options, function(err, data) {
if (err) return reject(err);
resolve(data);
});
});
}
Promise.all(files.map(fsReadFileP)).then(function(results) {
// files data in results Array
}, function(err) {
// error here
});
Mavi kuş Promise.map()
vePromise.promisifyAll()
const Promise = require('bluebird');
const fs = Promise.promisifyAll(require('fs'));
const files = ["file1.txt", "fileA.txt", "fileB.txt"];
Promise.map(files, fs.readFileAsync).then(function(results) {
// files data in results Array
}, function(err) {
// error here
});
Bluebird'in vaat ettiği ve Promise.map()
uzaktaki bir ana bilgisayardan bir kerede en fazla 4 okuyabileceğiniz, ancak izin verilen sayıda paralel tutmak istediğiniz bir grup URL'yi okurken , düz Promises'a bir örnek :
Plain JS Vaatleri
const request = require('request');
const urls = [url1, url2, url3, url4, url5, ....];
// make promisified version of request.get()
function requestGetP(url) {
return new Promise(function(resolve, reject) {
request.get(url, function(err, data) {
if (err) return reject(err);
resolve(data);
});
});
}
function getURLs(urlArray, concurrentLimit) {
var numInFlight = 0;
var index = 0;
var results = new Array(urlArray.length);
return new Promise(function(resolve, reject) {
function next() {
// load more until concurrentLimit is reached or until we got to the last one
while (numInFlight < concurrentLimit && index < urlArray.length) {
(function(i) {
requestGetP(urlArray[index++]).then(function(data) {
--numInFlight;
results[i] = data;
next();
}, function(err) {
reject(err);
});
++numInFlight;
})(index);
}
// since we always call next() upon completion of a request, we can test here
// to see if there was nothing left to do or finish
if (numInFlight === 0 && index === urlArray.length) {
resolve(results);
}
}
next();
});
}
Mavi Kuş Vaatleri
const Promise = require('bluebird');
const request = Promise.promisifyAll(require('request'));
const urls = [url1, url2, url3, url4, url5, ....];
Promise.map(urls, request.getAsync, {concurrency: 4}).then(function(results) {
// urls fetched in order in results Array
}, function(err) {
// error here
});