Knex: bagaimana cara mengkonfigurasi untuk menggunakan Janji ES6 standar?

Dibuat pada 22 Jul 2016  ·  80Komentar  ·  Sumber: knex/knex

saat menjalankan dengan node v6, apakah ada cara untuk mengonfigurasi agar hanya menggunakan Janji ES6 standar (hilangkan ketergantungan bluebird)?

misalnya dalam paket janji-antrian, default untuk menggunakan apa pun yang tersedia secara global Janji,

https://www.npmjs.com/package/promise-queue

atau pengguna dapat secara eksplisit mengonfigurasinya dengan Queue.configure(require('vow').Promise);

Jadi bisakah paket ini menerapkan strategi serupa?

discussion

Komentar yang paling membantu

:+1: untuk Janji asli.

Semua 80 komentar

Penasaran: Anda ingin mengganti perpustakaan yang lebih cepat dengan yang lebih lambat? Pada klien itu tidak masalah tetapi dalam kecepatan simpul adalah faktor. Apa alasan Anda untuk ini?

@johanneslumpe Ini adalah faktor dalam beberapa aplikasi, dengan knex Saya sangat ragu bahwa pustaka Promise yang digunakan memiliki efek signifikan terhadap kinerja. Telah dibahas bahwa kita harus menulis semua kode Promise hanya menggunakan A+ API sehingga bluebird tidak diperlukan.

Setelah itu harus mudah untuk ditimpa, perpustakaan Promise mana yang digunakan.

Saya setuju rasanya tidak ada gunanya di perpustakaan seperti knex. Mengingat bahwa basis kode knex sudah mengimpor file promise.js -nya sendiri secara internal, secara teknis masih akan sangat mudah untuk diimplementasikan, asalkan API-nya sama _(yang saya tidak yakin itu?)_. Dalam file ini seseorang dapat default ke janji global, jika tidak memerlukan perpustakaan yang dikonfigurasi, atau sesuatu seperti itu.

ini semua tentang memberi pengguna pilihan; untuk pengguna Node V6+, berikan pilihan untuk mengelola dependensi pihak ke-3 seminimal mungkin.

Penasaran: Anda ingin mengganti perpustakaan yang lebih cepat dengan yang lebih lambat?

apa yang Anda katakan mungkin benar di masa lalu, tetapi bagaimana dengan sekarang atau 6 bulan kemudian? (Saya melakukan pencarian dan hanya dapat menemukan beberapa tolok ukur 2015, jika Anda memiliki perbandingan yang lebih baru, silakan kirim beberapa tautan)
Saya percaya inti dari menjadikan Promise sebagai standar ES6 adalah agar orang dapat dengan mudah menggunakan Promise, tidak harus bergantung pada perpustakaan pihak ke-3, dan tim inti Node atau V8 tidak dapat buta akan perbedaan kinerja selamanya, selama lisensi open source kedua proyek kompatibel, mereka bahkan dapat meminjam beberapa kode; atau beri mereka waktu. Saya yakin Janji bawaan bisa lebih cepat dan lebih baik.

lihat AWS-SDK Amazon: ini juga default untuk menggunakan Promise apa pun yang tersedia secara global; sambil memberi pengguna pilihan untuk mengonfigurasi perpustakaan Promise favorit juga

http://docs.aws.amazon.com/AWSJavaScriptSDK/guide/node-making-requests.html#Support_for_Promises

ini semua tentang pilihan

Setelah dipikir-pikir, itu tidak akan semudah mengubah satu file. Knex saat ini sangat bergantung pada fungsi utilitas Bluebird seperti .timeout , .tap , .reduce , .map dan seterusnya, yang saya asumsikan dan harapkan tidak ada di ES6 Janji.

Saya tertarik untuk mendukung janji ES6. Idealnya kita memerlukan argumen kedua untuk konstruktor Knex yang membutuhkan konstruktor Promise . Kompatibilitas kembali akan dicapai seperti:

const Promise = require('bluebird');
const knex = Knex(myKnexConfig, Promise);

Mungkin kita bisa secara kondisional alias map , filter dll berdasarkan kehadiran mereka pada Promise.prototype yang disediakan?

Saya pikir ini harus cukup rendah pada daftar prioritas, dan itu akan memerlukan sedikit perubahan internal, belum lagi penurunan kinerja (meskipun memang belum melihat tolok ukur dalam beberapa saat) dan fakta bahwa orang mungkin mengandalkan pada fakta bahwa janji yang dikembalikan adalah bluebird (untuk bersyarat catch , dll).

Saya akan lebih cenderung menunggu sampai async/menunggu mendarat di simpul stabil untuk melihat mengatasi ini.

untuk orang yang menginginkan dependensi pihak ke-3 minimum, Janji asli bisa lebih baik,

seperti @google-cloud dan banyak perpustakaan lainnya, Anda dapat menjadikannya default untuk menggunakan Promise asli dan menerima parameter janji untuk siapa yang ingin menggunakan perpustakaan pihak ketiga

https://googlecloudplatform.github.io/google-cloud-node/#/docs/google -cloud/

var gcloud = require('google-cloud')({
  promise: require('bluebird')
});

@tgriesser Saya tahu ini adalah masalah lama, tapi sekarang kita punya async / await di stable dan Carbon.

Mengingat bahwa async/await bekerja dengan janji asli lebih disukai ( sesuai spesifikasi, fungsi async harus mengembalikan janji asli ) apakah ini prioritas yang lebih tinggi?

Jika dukungan janji asli adalah sesuatu yang Knex inginkan terjadi, tetapi saat ini tidak ada dalam radar, apakah PR akan diterima?

Terima kasih atas waktunya.

@malexdev async fungsi mengembalikan janji asli itu tidak ada hubungannya dengan knex saat ini. Itu tidak berarti bahwa await membutuhkan janji asli untuk berfungsi dengan baik. Bisakah Anda mengklarifikasi dalam hal ini masalah/manfaat (kecuali menjatuhkan satu ketergantungan)?

Meskipun demikian, saya tidak menentang menjatuhkan bluebird, tetapi itu benar-benar membutuhkan sedikit perubahan internal. Kita mungkin perlu mengimplementasikan beberapa metode yang saat ini diekspos dari bluebird ke knex API, kecuali fungsionalitas lama disembunyikan di bawah beberapa sakelar konfigurasi dan secara default janji asli akan digunakan. Migrasi dengan cara ini bukanlah hal yang mustahil bagi orang-orang yang telah menyampaikan fakta bahwa knex mengembalikan janji bluebird .

@elhigu Manfaat utama bagi saya pribadi adalah saya menggunakan TypeScript dengan aturan TSLint yang memberlakukan janji asli yang digunakan untuk await , jadi saya harus membungkus semua panggilan Knex di dalam Promise.resolve() . Saya menyadari ini tidak ada hubungannya dengan Knex secara khusus, dan kemungkinan merupakan masalah yang unik bagi saya.

Selain itu menurut saya memiliki lebih sedikit ketergantungan pihak ke-3 lebih baik, dan seperti yang disebutkan @c0b lebih banyak opsi tidak pernah merupakan hal yang buruk.

Saya menyadari bahwa ini akan menjadi banyak pekerjaan, yang merupakan salah satu alasan saya lebih dari senang untuk menghabiskan waktu ini, jika itu adalah sesuatu yang Knex tertarik untuk bergerak.

Ya, saya mendarat di sini karena masalah TypeScript - Saya menggunakan Knex sebagai mesin SQL untuk perpustakaan penyimpanan data multi-penyimpanan saya, dan sementara saya ambivalen vis-a-vis asli vs janji bluebird, saya tidak dapat dengan mudah menggunakan TypeScript di knex karena alasan ini. Saya memperlakukan knex thenables sebagai mengikuti spesifikasi asli (saya tidak menggunakan ekstensi bluebird apa pun), tetapi TypeScript mengganggu saya tentang mengembalikan Bluebirdketika deklarasi metode adalah Janji.

Ini adalah semacam dua level jauh di sini, karena kita berurusan dengan implementasi janji dan pengetikan untuk knex (yang ditangani oleh pengembang yang berbeda), tetapi pada dasarnya saya terjebak di sini - saya secara teknis melanggar kontrak tipe oleh mengembalikan Bluebird ketika saya mendeklarasikan Promise (saya kira ada hal-hal di api Promise yang tidak didukung Bluebird?) tetapi saya juga tidak ingin meletakkan banyak return Promise.resolve(bluebirdthing) di mana-mana.

Saya telah menghabiskan cukup waktu untuk menggali nyali knex selama setahun terakhir dan bekerja dengan janji-janji secara umum bahwa saya akan bersedia untuk mengambil sesuatu di sini dan mengerjakan PR untuk memodulasi implementasi Promise jika orang mau - maukah Anda terbuka untuk PR? Itu akan berakhir menjadi sesuatu seperti yang disebutkan @elhigu - mengimplementasikan kembali beberapa fungsi utilitas untuk menggunakan konstruktor Promise apa pun yang diteruskan saat instantiasi sehingga untuk menghindari kebutuhan penulisan ulang kode. Tidak yakin tentang kinerja, tentu saja, tetapi itu adalah sesuatu yang dapat dijadikan tolok ukur.

Setelah semuanya selesai dengan async/menunggu akan keren juga, dan saya tidak terburu-buru untuk memperbaikinya (pada akhirnya untuk kasus penggunaan saya, saya akhirnya menandai hal-hal sebagai any dan berurusan dengan itu codebranch seolah-olah mereka javascript bukan TypeScript).

@ericeslinger Saya tidak mengerti mengapa implementasi Janji nyata yang digunakan akan menyebabkan masalah dengan TypeScript, saya telah mencampurkan janji bluebird dan asli selama satu setengah tahun tanpa masalah ...

Saya hanya belum pernah menggunakan pengetikan apa pun yang akan memperkenalkan tipe untuk bluebird, saya hanya memberi tahu pengetikan TypeScript bahwa itu adalah Janji normal dan tidak melihat perbedaan apa pun (ofc. itu akan mengeluh jika saya mencoba menggunakan metode khusus bluebird).

Versi TypeScript mana dan apakah ada contoh proyek untuk direproduksi... misalnya github repo dengan npm start script.

Ini adalah semacam dua level jauh di sini, karena kita berurusan dengan implementasi janji dan pengetikan untuk knex (yang ditangani oleh pengembang yang berbeda), tetapi pada dasarnya saya terjebak di sini - saya secara teknis melanggar kontrak tipe oleh mengembalikan Bluebird ketika saya telah mendeklarasikan Promise (saya kira ada hal-hal di api Promise yang tidak didukung Bluebird?) tetapi saya benar-benar tidak ingin meletakkan banyak Promise.resolve(bluebirdthing) kembali di mana-mana.

Apakah itu pengetikan knex dari npm? Apakah pengetikan bluebird dari npm? Paket yang mana? Saya kesulitan memahami mengapa itu bisa terjadi. Jika ada jenis Bluebird yang terpisah, itu harus diwarisi dari janji asli dan boleh saja untuk kembali dari API yang memberi tahu bahwa mereka akan mengembalikan Janji. Dari uraian tersebut terdengar bahwa masalah implementasi pengetikan sangat rusak. Dan itu tidak relevan dengan masalah ini (TypeScript tidak keberatan dengan tipe asli, jadi itu tidak akan tahu apa yang dikembalikan knex).

Saya mendapatkan pengetikan dari repo PastiTyped dengan menginstal @types/knex . Definisi itu menariknya @types/bluebird , dan semua metode knex diketik sebagai objek Bluebird yang kembali.

Sebagai hal yang spesifik, saya tidak dapat melakukan ini:

function mungeData(v: any): DataItem {} 
function foo(): Promise<DataItem[]> {
  return knex('data').select()
  .then((rows) => rows.map(row => mungeData(row)))
} // error, cannot return Bluebird<DataItem[]> as Promise<DataItem[]>

menggunakan pengetikan ini. Ini karena knex.select().then() diketik untuk mengembalikan Bluebird di repo PastiTyped, dan rantai itu bersama-sama untuk membuat lebih banyak Bluebird, dan mengatakan sesuatu seperti return foo as Promise<any>() ketika foo adalah Bluebirdakan gagal (setidaknya gagal dalam TypeScript 2.4), karena Bluebirds tidak dapat ditetapkan ke Promises (mereka tidak memiliki [Symbol.toStringTag] menurut this , jadi memaksa satu sama lain akan menjadi kesalahan, meskipun kesalahan kecil).

Sebaliknya saya bisa berubah menjadi

function bar(): Promise<DataItem[]> {
  return Promise.resolve<DataItem[]>(foo())
}

atau lakukan trik lain untuk membungkus semua panggilan ke knex di dalam panggilan Promise.resolve() asli. Ini akan menyebabkan TypeScript berhenti mengeluh hilir fungsi perpustakaan saya, sementara masih memungkinkan saya untuk menggunakan pengetikan knex di dalam fungsi perpustakaan saya.

Sebelumnya kemarin, saya tidak pernah menggunakan @types/knex sama sekali - saya hanya mengetik knex sebagai any . Kode berfungsi dengan baik saat runtime (setidaknya untuk kasus penggunaan saya), hanya saja

@elhigu : Masalahnya bukan implementasi pengetikan yang rusak.
TypeScript menetapkan jenis untuk async berfungsi sebagai Promise<[type]> , yang benar per spesifikasi JS.
Knex mengembalikan Bluebird<[type]> , yang dicerminkan oleh pengetikan secara akurat.

Saya hanya belum pernah menggunakan pengetikan apa pun yang akan memperkenalkan tipe untuk bluebird, saya hanya memberi tahu pengetikan TypeScript bahwa itu adalah janji normal dan tidak melihat perbedaan apa pun

Ini berbohong kepada kompiler, karena fungsi Knex sebenarnya mengembalikan Bluebird s. Tidak tertarik.
Anda benar bahwa Bluebirds kompatibel dengan Promises, tetapi bagian dari kesepakatan dengan TypeScript adalah Anda benar-benar mengembalikan apa yang Anda katakan Anda kembalikan.

Saat mengembalikan Bluebird dari fungsi yang telah diketik untuk mengembalikan Promise , TypeScript mengeluh karena tipe Bluebird tidak sama dengan tipe Promise .
Ada berbagai trik yang bisa kita lakukan (seperti apa yang @ericeslinger sebutkan tentang menggunakan any , atau membungkus Promise.resolve() ) tetapi pada akhirnya trik seperti itu membuat kita kehilangan banyak apa yang disediakan TypeScript.

Pada akhirnya, kenyataannya adalah setidaknya ada dua pengguna sekarang yang mengatakan "Menggunakan janji asli penting bagi kami, dan kami bersedia bekerja untuk membuat fungsi janji lebih umum".

Saya sadar Anda hanya mencoba membantu, tetapi terus terang alih-alih mendengar "Anda bisa melakukannya dengan cara ini", saya ingin mendengar apakah perubahan janji yang diajukan oleh saya sendiri / @ericeslinger / @c0b dapat diterima sehingga saya dapat memulai pada PR atau apa.

@malexdev @ericeslinger Terima kasih untuk info lebih lanjut! Sepertinya sebenarnya tidak mungkin mewarisi kelas Anda sendiri dari Promise sehingga mungkin menjadi alasan mengapa mengembalikan Bluebirds dari fungsi yang diketik menjadi Janji<> gagal :(

@ericeslinger Bagaimanapun ini bukan masalah ketika Anda membuat fungsi async , karena mereka secara otomatis membungkus hasil ke janji asli secara internal. Mengikuti sesuai tanpa masalah, dengan mengetik dari @types/bluebird dan dikompilasi ke ES2015 atau ESNEXT.

import * as Bluebird from 'bluebird';

// declaring function async converts bluebird implicitly to native Promise
async function asyncReturningPromise(): Promise<string> {
    const blueBirdPromise = new Bluebird<string>((resolve, reject) => { 
        resolve('yay asyncReturningPromise');    
    });
    return blueBirdPromise;
}

// main func to run the code using async / await
Bluebird.resolve().then(async () => {
    console.log("await function returning promise (bluebird)", await asyncReturningPromise());

    const blueBird = new Bluebird((resolve, reject) => { resolve(); });
    const returnedFromAsync = asyncReturningPromise();

    console.log("Bluebird instanceof Promise:", blueBird instanceof Promise);
    console.log("async retval instanceof Promise:", returnedFromAsync instanceof Promise);
});

keluaran:

await function returning promise (bluebird) yay asyncReturningPromise
Bluebird instanceof Promise: false
async retval instanceof Promise: true

Jadi untuk saat ini ketika Anda menggunakan knex API untuk saat ini, Anda sebenarnya perlu memberi tahu bahwa Anda mengembalikan Bluebird kecuali jika Anda menggunakan fungsi/metode async, yang membungkus bluebird secara otomatis ke Promises asli.

@malexdev

Ini berbohong kepada kompiler, karena fungsi Knex benar-benar mengembalikan Bluebirds. Tidak tertarik.
Anda benar bahwa Bluebirds kompatibel dengan Promises, tetapi bagian dari kesepakatan dengan TypeScript adalah Anda benar-benar mengembalikan apa yang Anda katakan Anda kembalikan.

Sebenarnya berurusan dengan TypeScript adalah cukup bahwa objek yang dikembalikan mengimplementasikan antarmuka dengan benar, misalnya ini baik-baik saja:

class FakePromise<T> implements Promise<T>  {
    [Symbol.toStringTag]: "Promise";
    then<TResult1, TResult2>(onfulfilled?: (value: T) => TResult1 | PromiseLike<TResult1> | null | undefined, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2> | null | undefined): Promise<TResult1 | TResult2> {
        return new Promise((resolve, reject) => { resolve('Im totally broken and fake!); });
    }
    catch<TResult>(onrejected?: (reason: any) => TResult | PromiseLike<TResult> | null | undefined): Promise<T | TResult> {
        throw new Error("Method not implemented.");
    }
}

// this works and  fake promise instance has nothing to do with native promise
function returningPromiseInterface(): Promise<string> {
    const fakePromise = new FakePromise<string>();
    return fakePromise;
}

// compiling this fails, because looks like Bluebird actually doesn't implement Promise interface correctly
function asyncReturningPromise(): Promise<string> {
    const blueBirdPromise = new Bluebird<string>((resolve, reject) => { 
        resolve('yay asyncReturningPromise');    
    });
    return blueBirdPromise;
}

Ini mengacaukan instanceof, tetapi TypeScript sebenarnya bahkan tidak menjanjikan bahwa Anda mengembalikan instance Promise asli, hanya antarmuka.

Saat mengembalikan Bluebird dari fungsi yang telah diketik untuk mengembalikan Promise, TypeScript mengeluh karena tipe Bluebird tidak sama dengan tipe Promise.
Ada berbagai trik yang bisa kita lakukan (seperti apa yang @ericeslinger sebutkan tentang menggunakan apapun, atau membungkus di Promise.resolve()) tetapi pada akhirnya trik seperti itu membuat kita kehilangan banyak dari apa yang disediakan TypeScript.

Saya tidak suka melihat orang harus melakukan trik semacam itu/mengubah implementasi JS hanya untuk memuaskan pengetikan yang buruk.

Pada akhirnya, kenyataannya adalah setidaknya ada dua pengguna sekarang yang mengatakan "Menggunakan janji asli penting bagi kami, dan kami bersedia bekerja untuk membuat fungsi janji lebih umum".

Saya sadar Anda hanya mencoba membantu, tetapi terus terang alih-alih mendengar "Anda bisa melakukannya dengan cara ini", saya ingin mendengar apakah perubahan janji yang diajukan oleh saya sendiri / @ericeslinger / @c0b dapat diterima sehingga saya dapat memulai pada PR atau apa.

Terima kasih atas pengertiannya :) Mengubah knex untuk menggunakan janji asli sudah dimulai dan diimplementasikan ke beberapa titik tahun lalu kemudian diubah kembali oleh @tgriesser jadi saya akan mengatakan bahwa untuk saat ini lebih baik tidak memulai perubahan ini.

Saya juga masih menganggap masalah TypeScript yang disebutkan di utas ini sebagai masalah dalam deklarasi pengetikan (mengapa bluebird tidak mengimplementasikan Promise dengan benar ... Saya perlu menggali lebih dalam tentang itu?), daripada masalah dalam implementasi knex.

Karena itu, saya tidak menentang menyingkirkan bluebird dalam beberapa waktu hanya melihat dua masalah terpisah di sini.

:+1: untuk Janji asli.

@elhigu :

Sebenarnya berurusan dengan TypeScript adalah cukup bahwa objek yang dikembalikan mengimplementasikan antarmuka dengan benar

Cukup adil. Saya masih berpegang pada pendapat saya bahwa lebih sedikit ketergantungan dan lebih banyak pilihan lebih baik, tetapi sekarang saya mengerti apa yang Anda maksud tentang pengetikan yang rusak.

Jadi masih 👍 untuk Janji asli (yang masih ingin saya bantu), tetapi saya melihat sekarang masalah langsung saya dapat diselesaikan dengan memperbaiki pengetikan Bluebird. Terimakasih atas infonya.

Jadi saya sudah mulai menggunakan TypeScript cukup sedikit dan saya menyukainya dan sekarang menyadari masalah di sini adalah titik rasa sakit yang nyata. Saat async/await mendapatkan lebih banyak pijakan di Node baru-baru ini, utilitas Bluebird fns ( map , reduce , tap , bind , return ) menjadi kurang berguna. Saya akan baik-baik saja dengan terus menggunakan Bluebird secara internal tetapi secara resmi "menghentikan" api publik pembuat kueri knex mengembalikan semua metode utilitas tambahan.

Dengan penggabungan itu, kita kemudian dapat meningkatkan definisi TypeScript untuk menghapus pengetikan Bluebird (kecuali untuk toBluebird ), dan mengubah pengetikan Bluebird menjadi pengetikan Promise.

Jika ada yang memiliki bandwidth ingin mengatasi ini, inilah yang saya pikirkan untuk rencana tindakan:

  • [ ] Tambahkan peringatan penghentian untuk semua metode proksi Bluebird ( tap , map , reduce , bind , return ).
  • [ ] Tambahkan metode .toBluebird() yang akan menjadi jalur migrasi bagi mereka yang ingin terus menggunakan Bluebird (mereka dapat melakukannya dengan menemukan/mengganti semua panggilan metode di atas dan tambahkan saja sebelumnya mereka disebut)
  • [ ] Setelah ini digabungkan/pemotongan rilis baru (0,15) kami dapat memperbarui definisi TypeScript
  • [ ] Akhirnya kita bisa menghentikan metode ini sepenuhnya. API yang lebih sederhana ini membuka jalan untuk akhirnya menggunakan Janji asli & async/menunggu saat masuk akal.

Beri tahu saya jika ini masuk akal dan jika ada yang tertarik untuk mencoba ini.

Pasti akan tertarik untuk membantu dengan ini.

Apakah ini berarti Knex akan mulai mempertahankan definisi TypeScript-nya sendiri? Akan memungkinkan kami melakukan beberapa hal keren dengan obat generik yang tidak akan pernah didukung oleh pengetikan otomatis.

Saya memulai garpu ini sebagai upaya pertama untuk menambahkan dukungan untuk Janji asli:
https://github.com/tgriesser/knex/pull/2523/files

Sukai komentar ini dari 2016:

Penasaran: Anda ingin mengganti perpustakaan yang lebih cepat dengan perpustakaan bawaan yang lebih lambat

Menakjubkan betapa banyak yang bisa berubah dalam 2 tahun.

Saat mengembalikan Bluebird dari fungsi yang telah diketik untuk mengembalikan Promise, TypeScript mengeluh karena tipe Bluebird tidak sama dengan tipe Promise.

@malexdev Sebenarnya TypeScript menggunakan pengetikan struktural (flow menggunakan pengetikan nominal dan akan bekerja seperti yang Anda gambarkan) selama jenis Anda memenuhi antarmuka Promise itu kompatibel dengan Promise apakah itu secara eksplisit extends / implements itu atau tidak.

Bagaimana perkembangannya? Saya rasa langkah pertama yang baik adalah memfaktorkan panggilan metode khusus Bluebird dalam knex (yaitu belum benar-benar menghapusnya). Menghapus bluebird dan memberikan opsi untuk konstruktor Promise khusus akan mengikuti (dan memberi orang-orang yang menggunakan metode Bluebird jalur peningkatan).

Saya tidak mulai mengerjakan langkah pertama jika tidak ada keberatan. Pekerjaan yang ada tampaknya telah mereda.

@qubyte Saya tidak berpikir ada upaya aktif untuk melakukan perubahan, perubahan bertahap dibuat di sana-sini, tapi itu saja.

Oke. Di waktu luang saya berikutnya, saya akan membuat beberapa perubahan sekecil mungkin untuk memperhitungkan setiap metode.

@tgriesser Ada pendapat kapan kita harus maju dengan yang ini (jika pernah)? Bagi saya April mendatang akan terdengar seperti waktu yang masuk akal untuk itu ketika Node 6 LTS mencapai akhir baris.

Informasi menarik di tahun 2018:

promises-native-async-await memiliki kinerja yang lebih baik daripada promises-bluebird di node 10.
Referensi: https://github.com/petkaantonov/bluebird/tree/master/benchmark

Jadi performa bukan alasan untuk memelihara bluebird lagi. Kita harus menggunakan async/menunggu.

janji-asli-async-menunggu memiliki kinerja yang lebih baik

itu juga yang sangat saya yakini pada tahun 2016 bahwa cara asli akan meningkat lebih cepat, hanya karena itu adalah inti dari komunitas Nodejs, memiliki lebih banyak orang yang peduli, lebih dari perpustakaan pihak ketiga mana pun

Sementara, tiket diajukan meminta pilihan, ada begitu banyak implementasi Promise yang bersaing, hanya saja tidak baik bertaruh pada bluebird selamanya

Apakah ada pembaruan tentang ini?

@cfanoulis Sama masih berdiri. Saat April tiba, kami dapat menghentikan dukungan untuk Node 6 dan mulai menghapus bluebird.

ada pembaruan 2019? /cc ke beberapa kontributor inti atau pengelola atau siapa pun @here yang peduli tentang itu: @johanneslumpe @tgriesser @wubzz @elhigu dari https://github.com/tgriesser/knex/graphs/contributors?type=c&from=2018-01- 01&sampai=2019-12-31

Di sisi lain, komunitas JavaScript adalah dunia yang dinamis, bersemangat, dan terkadang kejam, setiap 3 atau 2 tahun (atau bahkan lebih cepat) ada pengganti untuk sesuatu yang kita kenal sebelumnya, pikirkan tentang Grunt, Gulp => Webpack, alat, perpustakaan, kerangka kerja sepenuhnya bersaing di setiap tingkat, Jadi, ke perpustakaan yang lebih lama jika Anda berhenti membawa inovasi, atau memperlambat mendukung standar baru (pikirkan tentang ES2019 async/menunggu iterator ...) Anda akhirnya akan diganti

Saya baru saja melakukan riset sederhana, sepertinya di level DB ORM juga ada banyak alternatif, TypeORM mungkin bagus ... (Saya berhenti di sini bukan untuk mengatakan lebih banyak ...)
https://bestofjs.org/tags/db
https://bestofjs.org/projects/typeorm

@c0b tidak perlu cc. Saya mendapatkan email dari semua komentar. @kibertoad baru saja mengatakan semua yang harus dikatakan dalam komentar terakhirnya... Masalah ini juga tidak ada hubungannya dengan knex yang mendukung async/menunggu fitur ES2019 lebih baik dan knex bukan ORM jadi saya tidak yakin apa komentar itu sebenarnya tentang.

Jika Anda membutuhkan ORM yang baik, saya dapat merekomendasikan keberatan.js. Ini diimplementasikan di atas knex juga, ini adalah utas yang cukup bagus tentang itu https://github.com/Vincit/objection.js/issues/1069

Pada titik tertentu knex ini akan diganti, tetapi tidak dengan ORM apa pun. Itu bisa diganti oleh beberapa pembuat kueri lain, yang memiliki basis kode yang lebih bersih dan API yang lebih konsisten. Seperti misalnya knex 1.0 mungkin ;)

Juga jika knex diganti, saya akan baik-baik saja dengan itu, lebih sedikit pekerjaan untuk saya: D

Ada WIP yang saya yakini: https://github.com/tgriesser/knex-next

Hanya ingin juga menyebutkan bahwa tidak menggunakan janji asli menghasilkan https://github.com/nodejs/node/issues/22360 saat menggunakan async_hooks yang menyebabkan konteks saat ini hilang.

Percayalah, kami tidak perlu alasan tambahan untuk pindah, kami ingin melakukannya seburuk yang Anda semua lakukan :). Namun, kami masih perlu merilis beberapa perbaikan lagi untuk cabang Node 6, dan kemudian (akhirnya), kami akan menghapusnya dan mulai menghapus bluebird secara bertahap.

Setelah #3227 digabungkan, akhirnya kita bisa mulai!

Saya tahu Anda telah menyebutkan sebelumnya bahwa Anda dapat menggunakan bantuan dalam migrasi ini, jika itu masih arah yang ingin Anda tuju, dapatkah kami membantu dengan cara apa pun?

Saya sedang berpikir: buat Proyek, tambahkan beberapa tugas, dan lihat apakah ada orang (mungkin saya punya waktu) dapat ditugaskan dan menetapkan beberapa tanggal?

@chaffeqa Akan segera membuat beberapa tugas yang lebih terperinci, siapkan #3250 untuk putaran pertama perubahan mudah. Terutama kita perlu mengganti penggunaan bluebird.tap, bluebird.method dan bluebird.try dengan sesuatu yang berbasis native. Jika Anda sudah memiliki waktu, Anda dapat mencoba bercabang #3250 dan melihat kebutuhan 'bluebird' yang tersisa (saya akan merekomendasikan memulai dengan yang tidak khusus dialek sehingga Anda dapat dengan cepat memvalidasi fungsionalitas yang masih berfungsi dengan menjalankan test:sqlite tanpa pengaturan Docker).

@qubyte Jika Anda ingin berkontribusi, sekaranglah waktunya!

@kibertoad apakah saya aman menggunakan async/menunggu sekarang?

Maksud Anda dalam basis kode knex? Tentu. Dalam diri Anda sendiri, Anda selalu ada :-D

Maaf telah menjadi MIA minggu lalu, hal-hal meningkat untuk perusahaan kami jadi saya harus fokus di sana.

Ingin menutup loop pada beberapa diskusi yang kami lakukan di salah satu blok yang lebih besar untuk peningkatan: mengganti Disposer penggunaan .

Ini adalah serigala yang cukup dalam ketika Anda mulai turun, jadi akan membutuhkan beberapa teknik yang bagus untuk memberikan salinan/abstraksi yang bagus. Saya khawatir overhead kinerja sesuatu mungkin cukup besar (lebih banyak objek dibuat saat rantai janji tumbuh).

Saya sebenarnya mulai dengan beberapa POC, dan saya pikir ini yang paling mudah:

class DisposablePromise extends Promise {

  disposerFunc = null;
  originalResource = null;

  then(onFulfilled, onRejected) {
    const $onFulfilled = this.wrap(onFulfilled);
    return super.then($onFulfilled, onRejected).copyContext(this);
  }

  copyContext(promise) {
    this.disposerFunc = promise.disposerFunc;
    this.originalResource = promise.originalResource;
    return this;
  }

  disposer(disposerFunc) {
    this.disposerFunc = disposerFunc
  }

  isDisposable() {
    return !!this.disposerFunc
  }

  wrap(onFulfilled: any) {
    const $onFulfilled = (result: any) => {
      if (this.disposerFunc && !this.originalResource) {
        this.originalResource = result
      }
      if (result instanceof Promise) {
        return onFulfilled(result);
      } else {
        const res = onFulfilled(result)
        if (this.disposerFunc) {
          this.disposerFunc(this.originalResource)
        }
        return res
      }
    };

    return $onFulfilled;
  }
}

Dan satu lagi:

      var DisposablePromise = function DisposablePromise() {
          var self = DisposablePromise.convert(Promise.resolve());
          return self;
      };
      DisposablePromise.convert = function convert(promise, props) {
          promise.__proto__ = DisposablePromise.prototype;
          return props ? Object.assign(promise, props) : promise;
      };
      DisposablePromise.prototype = Object.create(Promise.prototype);
      DisposablePromise.prototype.constructor = DisposablePromise;
      DisposablePromise.prototype.then = function then(resolve, reject) {
          var returnVal = Promise.prototype.then.call(this, resolve, reject);
          return DisposablePromise.convert(returnVal);
      };
      DisposablePromise.prototype.catch = function _catch(err) {
          var returnVal = Promise.prototype.catch.call(this, err);
          return DisposablePromise.convert(returnVal);
      };
      DisposablePromise.prototype.finally = function finall(obj) {
          var returnVal = Promise.prototype.finally.call(this, obj);
          return DisposablePromise.convert(returnVal);
      };
      DisposablePromise.prototype.disposer = function disposer(disposerFunc) {
        var returnVal = Promise.prototype.finally.call(this, obj);
        return DisposablePromise.convert(returnVal);
      };

Tapi belum sempat membuktikannya.

Saya pikir mungkin bermanfaat untuk benar-benar menjelajahi opsi lain (simpan bluebird tetapi ubah untuk menggunakan janji asli secara internal?) karena fakta bahwa fitur ini harus ada di repositori (kecuali jika Anda dapat memikirkan pendekatan yang lebih baik ... async iterators? Akan senang mendengar pemikiran apa pun dari tim bluebird bahkan tentang mengabstraksi fungsi itu, meskipun naluri saya mengatakan itu cukup terkait dengan kait implementasi bluebird.

Saya akan mengatakan jika kita dapat mengetahui bagian ini, sisa tugas-tugas itu cukup mudah.

@chaffeqa Np, menghargai Anda masih menemukan waktu untuk kembali ke ini!
Saya sangat ragu orang-orang bluebird akan terbuka untuk saran untuk merekayasa ulang implementasi mereka secara serius, mereka telah berulang kali menegaskan kembali poin bahwa pada titik ini mereka tertarik pada stabilitas di atas segalanya, dan mereka merekomendasikan orang untuk benar-benar menggunakan janji asli kecuali jika benar-benar membutuhkan fitur-fitur canggih disediakan oleh Blue Bird.
Mempertimbangkan bahwa Node 8 tampaknya menjadi versi Node.js yang paling populer saat ini (berdasarkan statistik unduhan resmi Node.js), saya khawatir kita belum bisa beralih ke pendekatan berbasis iterator async dulu.
Kelemahan apa yang Anda lihat dari Knex yang mengimplementasikan DisposablePromise secara internal? Karena itu memperluas Promise asli, saya berasumsi itu tidak membawa kekurangan Bluebird dengannya, dan tidak ada di ruang pengguna yang perlu tahu tentang itu?

@ericeslinger FWIW, pengetikan TS seharusnya tidak menjadi masalah lagi di master, kami mengetik janji kami sebagai yang asli sekarang untuk mencegah pengguna mengandalkan fitur Bluebird. Ini dapat menyebabkan masalah di kemudian hari ketika Promises asli menerapkan sesuatu yang tidak dijanjikan Bluebird, jadi kami masih ingin mengganti janji yang digunakan sebanyak mungkin. Setiap kontribusi di sepanjang garis ini akan sangat dihargai :)

Kacang yang saya pikir sebanyak
Saya setuju melakukan sesuatu seperti DisposablePromise mungkin adalah cara yang harus dilakukan dalam kasus ini, terutama karena item yang benar-benar dibutuhkan masih dalam proposal .

Kelemahannya adalah akan sangat penting untuk merekayasa sesuatu seperti DisposablePromise dengan cara yang bijaksana... Ha).

Jika ada orang lain di utas ini yang ingin mencoba masalah ini <3 u lama!

@chaffeqa Seberapa rumit implementasi Bluebird? Mungkin kita bisa mengekstraknya dan menambahkannya di atas janji asli?

@chaffeqa Skenario kasus terburuk - kami dapat menghapus semua penggunaan Bluebird lainnya dan mempertahankan yang ini karena kerumitannya jika kami menganggapnya terlalu berisiko untuk disentuh. Tidak ideal, tetapi akhirnya using akan terjadi.

sayangnya cukup rumit ... implementasi mendukung fakta bahwa bluebird mengontrol siklus hidup janji. Saya pikir pendekatan terbaik adalah melihat apa yang coba dilakukan (yang cukup dekat dengan tautan pada using di atas) dan buat shim sesederhana dan seperforma mungkin untuk itu.

Masalahnya adalah bahwa pipeline harus berupa janji gaya Bluebird , yang jika saya pahami dengan benar, tidak mematuhi kinerja janji asli (dan karena itu Anda kehilangan semua penelusuran + fungsionalitas async asli).

Saya lebih suka melakukan sesuatu yang di bawah tenda menggunakan janji asli untuk bagian async, tetapi menyediakan kemampuan untuk mengikat konteks dan mengimplementasikan penggunaan yang diperlukan seperti disposer .

FYI hal lain dalam pikiran saya adalah: sebenarnya ada sedikit penggunaan usage dan .disposer di knex, jadi mungkin pendekatannya bekerja lebih baik untuk memindahkannya ke tingkat yang lebih tinggi?

Layak untuk dicoba :)

oooo juga opsi yang saya temukan berdasarkan https://github.com/petkaantonov/bluebird/issues/1593

Either way, saya pikir langkah maju yang baik adalah apa yang Anda mulai di cabang sebelumnya, di mana kami mengisolasi semua penggunaan Promise yang sebenarnya adalah BluebirdPromise , dengan cara itu kami dapat mulai bermain-main dengan menjatuhkan dalam penggantian seperti DisposablePromise atau BluebirdNativePromise .

@chaffeqa Maksudmu bagian Bluebird.setScheduler(fn => Promise.resolve().then(fn)) ?
Konversi keseluruhan berjalan sangat lancar! Jika kita bisa menyimpan Disposers di Bluebird sambil membuatnya menggunakan janji asli di bawah tenda, itu mungkin sebenarnya solusi yang bagus.

Hanya ingin menyebutkan juga bahwa tidak menggunakan janji asli menghasilkan nodejs/node#22360 saat menggunakan async_hooks yang menyebabkan konteks saat ini hilang.

Solusinya adalah menggunakan https://github.com/TimBeyer/cls-bluebird patch.

Sekadar informasi, LTS untuk Node v8 berakhir tahun ini.

Konteks @Bessonov ? Bagaimana menabrak min node ke 10 memengaruhi masalah ini? Perhatikan bahwa kami sudah menjatuhkan dukungan node 6.

Saya tidak terbiasa dengan basis kode knex, tetapi mungkin ada beberapa fitur, yang dapat membantu Anda menyingkirkan bluebird. Misalnya, node 10 memiliki dukungan untuk Promise.finally .

Tapi bagaimanapun, saya senang melihat perkembangan topik ini :+1:

Tentang pola pembuang - bisakah kita menambahkan panggilan balik opsional untuk hal-hal, yang mengembalikan janji sekali pakai?
(Sama halnya dengan transaksi)

getDisposableConnection(config, cb) {
    const connection = await getConnection(config)

   // user want autodisposable connection
    if (cb) 
      Promise.resolve(cb(connection)).then(() => connection.dispose())
   // user will dispose by himself
   return connection
}

Tingkat independensi perpustakaan yang menjanjikan yang kita butuhkan?
1) semua menggunakan janji asli
2) janji asli internal, pengguna dapat mengatur lib janji sendiri untuk antarmuka
3) pengguna dapat mengatur lib janji untuk internal dan antarmuka

Bagaimana keadaan saat ini dari masalah ini. Umumnya knex bekerja sekarang dengan async menunggu tetapi TypeScript akan melaporkan peringatan bahwa kami menunggu metode yang bukan janji asli.

Jadi untuk menjawab pertanyaan masalah asli. Solusi saat ini adalah menunggu dan menambahkan sesuatu seperti // tslint:disable-next-line: await-promise

@maximelkin Saya memilih opsi 1. Dalam jangka panjang saya berharap setiap perpustakaan janji akan usang.

id kedua bahwa, pada titik ini kami melampaui polyfill yang dijanjikan bahkan untuk sebagian besar browser

@Bessonov saat ini bergantung pada perpustakaan knex (dan mungkin proyek), yang membutuhkan bluebird

kita harus memberikan beberapa solusi mundur untuk mereka

@Bessonov saat ini bergantung pada perpustakaan knex (dan mungkin proyek), yang membutuhkan bluebird yang tepat, kita harus memberikan beberapa solusi mundur untuk mereka

Tidak masalah jika pengguna knex bergantung pada bluebird. Knex masih dapat menggunakan janji asli dan mereka akan beroperasi dengan baik dengan janji bluebird. Kami sama sekali tidak boleh memberikan fallback.

Jadi masalah ini dimulai dengan permintaan fitur dengan memilih implementasi janji.
Entah dari mana, itu bermutasi untuk menghapus bluebird tanpa alasan, dan menghancurkan semua tanggungan. Tanpa peringatan, changelog, opsi untuk mundur dan rilis utama.

Tapi saya kira semua pengguna 1.5 TypeScript senang sekarang.

Jadi masalah ini dimulai dengan permintaan fitur dengan memilih implementasi janji.
Entah dari mana, itu bermutasi untuk menghapus bluebird tanpa alasan, dan menghancurkan semua tanggungan. Tanpa peringatan, changelog, opsi untuk mundur dan rilis utama.

Setidaknya sebelumnya dengan knex versi 0.x telah dianggap sebagai rilis utama dengan perubahan yang berpotensi melanggar, jadi hanya memperbarui ke 0.20.x seharusnya dianggap sebagai peningkatan yang aman (semver benar-benar longgar ketika nomor versi <1).

Menghapus bluebird telah ada di meja untuk waktu yang lama, ini bukan hanya tentang masalah ini.

menghapus bluebird tanpa alasan

Menghapus bluebird bukan tanpa alasan. Anda masih dapat menggunakan bluebird secara eksternal dengan janji knex. Salah satu alasan besar untuk membuang bluebird adalah bahwa fungsi async secara implisit membuat janji asli, jadi di masa mendatang tetap menggunakan Bluebird akan memerlukan kode pembungkus bluebird tambahan untuk ditambahkan di knex API tanpa alasan apa pun.

Tanpa peringatan apapun, changelog,

Sepakat. Saya menelusuri changelogs terbaru... Sayangnya sepertinya kami gagal membuat daftar perubahan yang melanggar antar versi. Kita harus lebih berhati-hati saat menulis changelog untuk benar-benar menunjukkan perubahan, yang merusak API lama. Misalnya banyak perubahan pengetikan sebenarnya akan merusak kode TS lama.

Ada masalah yang sama pada proyek ioredis https://github.com/luin/ioredis/commit/da60b8b. Mereka ingin mendukung janji asli - dan teman-teman membuat solusi yang sangat bagus - mereka menambahkan opsi untuk mendukung perpustakaan janji khusus apa pun dan mereka menggunakan janji asli secara default. Kenapa tidak? Menyetel perpustakaan janji khusus cepat dan tidak perlu menambal semua kode aplikasi.

terus menggunakan Bluebird akan membutuhkan kode pembungkus bluebird tambahan untuk ditambahkan di knex API tanpa alasan apa pun.

Ya. Tetapi mengapa tidak membungkus panggilan modul di bluebird (atau perpustakaan janji lainnya) jika secara eksplisit ditentukan? Itu satu pembungkus sederhana, nol overhead, dan itu akan memungkinkan pengguna untuk menggunakan perpustakaan janji apa pun yang mereka inginkan. Jika tidak ada yang membutuhkan bluebird, tidak ada yang akan menggunakan opsi ini, dan Anda dapat dengan aman menghentikannya tepat waktu.

Juga, saya melihat pendapat bahwa

Dalam jangka panjang saya berharap setiap perpustakaan janji akan menjadi usang.

Tapi IMHO ada dua asumsi yang salah:

  • Bluebird digunakan karena lebih cepat.
  • Bluebird digunakan sebagai pollyfill.

Saya pikir itu tidak berlaku untuk aplikasi yang sangat kompleks, yang melampaui async-wait one liners.
Bluebird memiliki banyak fitur yang mutlak diperlukan untuk aliran asinkron yang kompleks - seperti batas waktu, penanganan kesalahan khusus, pemetaan dengan konkurensi, pembatalan, pengurangan, dan sebagainya. Semua fitur tersebut dapat diimplementasikan dalam janji asli, tetapi itu banyak boilerplate yang tidak berguna. Pada tahun 2020, kami masih menggunakan bluebird di Node 12 karena kami tidak menginginkan semua boilerplate ini.

Kenapa tidak? Menyetel perpustakaan janji khusus cepat dan tidak perlu menambal semua kode aplikasi.

Apa pun yang menggunakan async-await secara internal akan memaksa janji ke janji asli, jadi opsi Anda menjadi membungkus output dari setiap metode dalam janji khusus atau melarang async-await dalam kode internal. Ini bukan usaha kecil seperti yang terlihat pada pemeriksaan pertama.

@qubyte

Ini bukan usaha kecil seperti yang terlihat pada pemeriksaan pertama.

Tidak, itu sesederhana yang sudah saya katakan. Anda membuat pembungkus untuk fungsi eksternal yang diekspor dan itu saja. Sekitar 10 baris kode. Dan tulis semua kode internal dengan cara apa pun yang Anda inginkan.

@jehy : Jangan ragu untuk mengirimkan PR untuk 10 baris kode tersebut jika Anda melihat cara langsung untuk mengimplementasikannya.

Saya juga akan meluangkan waktu hari ini untuk mencoba menyelesaikan masalah.

Untuk apa nilainya, sebagian besar API bluebird diduplikasi dengan API yang sama atau dekat menggunakan janji asli oleh paket-paket ini: https://github.com/sindresorhus/promise-fun

Untuk apa nilainya, sebagian besar API bluebird diduplikasi dengan API yang sama atau dekat menggunakan janji asli oleh paket-paket ini

~50 paket bukannya 1? Dengan serius?

Ya, meskipun sebagian besar waktu hanya sedikit yang diperlukan (p-map misalnya). Jarak tempuh Anda dapat bervariasi tentu saja. Ini ditawarkan hanya sebagai satu rute potensial untuk apa yang Anda inginkan.

@jehy : Ini adalah sesuatu yang dapat Anda coba sebagai solusi sementara dalam kode aplikasi Anda:

const Bluebird = require('bluebird');


const prototypesNeedingDecoration = [
  require('knex/lib/query/builder').prototype,
  require('knex/lib/schema/builder').prototype,
  require('knex/lib/transaction').prototype,
  require('knex/lib/raw').prototype,
];

const corePromiseMethods = ["then", "catch", "finally"];


function decoratePromiseMethods(target) {
  for(const m of corePromiseMethods) {
    const original = target[m];

    target[m] = function(...args) {
      return Bluebird.resolve(original.apply(this, args))
    }
  }  
}

function hackBluebird() {
  for(const target of prototypesNeedingDecoration) {
    decoratePromiseMethods(target);
  }
}


hackBluebird();

Ini sebenarnya bukan solusi yang memadai untuk masalah keseluruhan. Ada objek sementara lainnya yang dibuat dalam knex yang perlu didekorasi dengan cara yang sama.

Juga, penafian: penyelesaian ️ hanya memiliki sedikit pengujian. Jadi, Anda harus menjalankan kembali pengujian aplikasi Anda untuk memastikan tidak ada yang rusak.

Hanya ingin menambahkan 2 sen saya di sini: saya sangat menghargai semua pekerjaan yang dilakukan dalam migrasi ini, terlepas dari umpan balik negatifnya.

Dari perspektif aplikasi kami, knex adalah perpustakaan terakhir yang memaksa kami untuk meminta Bluebird, dan sesuai dengan dukungan janji asli penuh berarti bahwa:

  1. kami tidak lagi menodai jejak tumpukan
  2. kami mengurangi berat SSR kami dengan jumlah yang layak
  3. kami meningkatkan kinerja karena async asli menunggu sekarang lebih berkinerja daripada bluebird (dan semakin berkembang!)

ini adalah kemenangan besar untuk terus berlari menuju standar es... dan saya tahu itu tidak mudah bagi pengelola perpustakaan, jadi saya ingin berteriak kepada kalian dan terima kasih telah menanggung beban seperti itu!

bagi mereka yang mengalami perubahan: Saya ingin membantu karena kami telah diuntungkan, jadi hubungi jika Anda memerlukan bantuan untuk men-debug atau bermigrasi!

@chaffeqa Terima kasih atas umpan balik ini, itu sangat berarti!

@jehy : Apakah Anda memiliki kesempatan untuk mencoba mengatasi yang diusulkan? Jika demikian, apakah itu menyelesaikan masalah langsung Anda?

Apakah halaman ini membantu?
0 / 5 - 0 peringkat