ES6 vaatlerimiz olduğu için Q veya BlueBird gibi vaat kütüphanelerini kullanmak için hala nedenler var mı? [kapalı]


229

Node.js vaatler için yerel destek ekledikten sonra, Q veya BlueBird gibi kütüphaneleri kullanmak için hala nedenler var mı?

Örneğin, yeni bir projeye başlıyorsanız ve bu projede bu kütüphaneleri kullanan herhangi bir bağımlılığınız olmadığını varsayalım, bu tür kütüphaneleri kullanmak için daha fazla neden olmadığını söyleyebilir miyiz?


4
yerli vaatlerin çok çok temel özellikleri vardır. Q veya Bluebird gibi kütüphaneler daha fazlasını ekler. Bu özelliklere ihtiyacınız varsa bu kütüphaneleri kullanın.
gman

7
Başlığı "ihtiyaç" ve "hala vaat kütüphaneleri kullanma nedenleri" hakkında daha az bilgi sahibi olacak şekilde düzenledim. Bu soru, görüş değil, öncelikle gerçekler sağlayarak cevaplanabilir. Yeniden açılmalıdır, çünkü öncelikle fikir değil, gerçekler sağlayarak cevaplanabilir. Bunun bir örneği olarak aşağıdaki cevaba bakınız.
jfriend00

11
@JaromandaX - Lütfen başlık ve soru, bir kişinin bir söz kitaplığı kullanmak için "ihtiyaç duyup duymadığı" yerine neden bir söz kitaplığı kullanacağına dair daha fazla bilgi almak için yeniden ayarlandığını tekrar açmayı düşünün. Benim düşünceme göre, bu soru, esas olarak fikir değil, gerçekler sağlayarak cevaplanabilir - aşağıdaki cevabı bunun bir örneği olarak görün.
jfriend00

6
Başlık düzenlemesinden sonraki bu soru ve kabul edilen cevabı görüşe dayalı değildir.
maksimum

7
Kabul. Bu şu anki haliyle mükemmel bir soru. Yeniden açılmak için aday gösterdim.
Jules

Yanıtlar:


368

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

  1. 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.

  2. Daha Hızlı - Bluebird, çoğu ortamda yerel vaatlerden önemli ölçüde daha hızlıdır .

  3. 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.

  4. Ç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. .).

  5. 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.

  6. 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
});

bazı şekillerde acı verici bir şekilde standart olmasa da - Şimdi "Promises / A + uyumlu" olduklarını iddia ediyorlar :) - blog.jquery.com/2016/01/14/jquery-3-0-beta-released
thefourtheye

1
@thefourtheye - Evet, 3.0'da Promise / A + uyumluluğu için çalıştıklarını biliyorum. Ama bu hala beta aşamasında. Sözü yerine getirirse (pun amaçlı), zaten jQuery kullanıyorsanız, JS tarayıcısında harici bir vaat kitaplığı kullanmanın bazı nedenlerini ortadan kaldırabilir. Bluebird'in yaptığı tüm kullanışlı özelliklere sahip olmayacak ve Bluebird'in performansına ulaşırsa son derece şaşırırım, bu nedenle bazı durumlarda gelecekteki bir jQuery ile birlikte Bluebird için hala yer var. Her durumda, OP'nin sorusu çoğunlukla node.js ile ilgili görünmektedir.
jfriend00

1
Son örnek kodda biraz yazım hatası yoktur: return new Promise(function(resolve, rejct). Olması gereken:reject
Sebastian Muszyński

7
util.promisifyDoğrudan promisifyAlleşdeğeri olmasa da, Node.js aslında şimdi var .
nyuszika7h

1
@Aurast - Evet, v11 ilgileniyor fs, ancak yine de bir grup paralel istekte bulunmanız gereken bir hedef hizmeti ezmekten kaçınmak için Bluebird'i (özellikle favorim concurrencyseçenek Promise.map()) kullanmak için başka nedenler . Ayrıca, Bluebird'in promisifyAll ile kullanmak için hala vaat edilmeyen diğer arayüzler. Ancak, yavaş yavaş her yeni projede Bluebird'i yakalamanın nedenleri, node.js'nin yerleşik vaat desteğini güçlendirdiği için soluyor.
jfriend00
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.