Definitelytyped: bluebird 3.0: bagaimana menggunakannya sebagai kelebihan untuk Janji global?

Dibuat pada 24 Agu 2016  ·  44Komentar  ·  Sumber: DefinitelyTyped/DefinitelyTyped

Hai semuanya!

Saya menggunakan bluebird sebagai pengganti objek Janji global. Saya mencoba memperbarui typedefs ke versi terbaru, diterbitkan oleh @lhecker , dan mengalami masalah: global Promsie sekarang tidak kelebihan beban secara default.
Bagaimana saya mencapai perilaku sebelumnya? Mungkin kita bisa memiliki bluebird-global.d.ts, misalnya?

Komentar yang paling membantu

Hai kawan,

@types/bluebird-global sekarang tersedia. Pengetikan ini menggunakan @types/bluebird@^3.0 di bawah kap mesin dan memungkinkan Anda untuk menggunakan metode bluebird pada Promise global (yaitu kompilasi ts tidak gagal).

Silakan baca ini untuk melihat cara menggunakannya.

Semua 44 komentar

Yah IMHO definisi Bluebird sebelumnya juga bukan solusi yang baik, karena mereka sangat bocor ke namespace global dan saya pikir itu adalah ide yang baik untuk mengurangi upaya yang berlebihan.

Cara kerja definisi sebelumnya adalah dengan mendefinisikan declare var Promise: PromiseConstructor; sedangkan PromiseConstructor adalah antarmuka Bluebird sebelumnya (didefinisikan secara global).

Yaitu jika Anda membuat file *.d.ts lokal dan menambahkan sesuatu seperti ini mungkin berhasil?

import Bluebird = require("bluebird");
declare var Promise: Bluebird<any>;

mungkin berhasil?

Sayangnya tidak ada. Karena saya punya banyak kode, yang ditulis seperti ini:

declare function doLoadData(): Promise<Data>

seperti yang Anda lihat, fungsi mengembalikan Promise<T> , yang merupakan standar Promsie , bukan bluebird. mendeklarasikan var Promise: Bluebird<any> Saya akan membebani konstruktor Promise standar, bukan antarmuka.

Saya beralih kembali ke pengetikan 2.0 karena alasan ini.

@Strate Ah sialan saya menulis komentar panjang tentang apa yang saya pikirkan tentang ini dan apa yang harus kita coba lakukan. Tapi sepertinya saya lupa menyerahkannya dan akhirnya hilang...

Banyak orang tampaknya memiliki masalah ini.

Saya membuat repo yang menunjukkan masalah: https://github.com/d-ph/typescript-bluebird-as-global-promise

git clone && npm install && npm run tsc

Masalah:
File d.ts pihak ke-3 diketik dengan Promise . Promise ini ditentukan oleh lib.es6.d.ts Typescript (ketika "target": "es6" ) atau oleh lib lain, misalnya core-js (sangat populer, saat mengkompilasi ke es5 dengan Typescript) . bluebird.d.ts terbaru tidak dideklarasikan sebagai global Promise , meskipun bluebird.js menampilkan dirinya sebagai global Promise .

Hasil:
Pengembang tidak dapat menggunakan fungsionalitas bluebird pada Janji yang dikembalikan dari kode pihak ke-3 (kompilasi gagal).

Hasil yang diharapkan:
Pengembang dapat menggunakan fungsionalitas bluebird pada Janji yang dikembalikan dari kode pihak ke-3 (kompilasi berhasil).

Saya tidak yakin siapa pengelola pengetikan bluebird. @lhecker , Anda adalah orang yang tidak beruntung yang dikembalikan oleh git blame . Bisakah Anda memberi tahu kami, apa yang lebih disukai mengapa menggunakan pengetikan bluebird sedemikian rupa, yang dikompilasi oleh proyek github, yang saya tautkan di atas?

Jalan-jalan saat ini:

  1. Yang paling kotor. Jangan pernah mengimpor bluebird dan jangan pernah menggunakan pengetikan bluebird. Untuk fungsi bluebird Promise gunakan ini: Promise["config"]({}); Promise.resolve("foo")["finally"](() => { console.log("lol"); }) untuk membungkam kompilator. Yaitu menggunakan operator akses array: [""]
  2. Kotor dan mengganggu. Di setiap entri file ts di aplikasi Anda, tambahkan dua baris ini:
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }

Untuk fungsi statis Bluebird, gunakan Bluebird.config({}) alih-alih Promise.config({}) .

Kelemahannya adalah, IDE kesulitan untuk menafsirkan peretasan ini dengan benar.

Hmm... Agak tidak terduga bagi saya bahwa kalian akan memiliki masalah dengan ini, karena Anda semua menggunakan Bluebird dengan cara yang saya dan banyak lainnya tidak. Bahkan saya sendiri tidak menulis pengetikan! Saya hanya menyalin satu-satunya yang ada untuk 3.0 dari sini , karena memiliki pengetikan untuk 3.0 lebih baik daripada tidak memilikinya, bukan?

Masalahnya adalah arah TypeScript saat ini menuju jelas modules > globals yang merupakan sesuatu yang sangat saya setujui. Tetapi ini juga berarti bahwa modul tidak boleh memodifikasi objek global, terutama jika Anda menganggap bahwa Bluebird tidak menggantikan Promise global dalam setiap kasus! Atau dengan kata lain:

Apa yang terjadi pada "keamanan tipe" Anda jika Anda memanggil Promise.noConflict() secara harfiah di mana saja dalam kode Anda? Ini akan mengembalikan tipe Promise global kembali ke yang asli dan membuat kode Anda macet, meskipun tsc memberi tahu Anda bahwa semuanya baik-baik saja.

Jadi ya... @d-ph. Langkah kedua Anda adalah apa yang seharusnya Anda pertimbangkan untuk dilakukan selama ini, karena itu dalam semangat sistem modul. Tapi saya tahu bahwa ini hanya solusi ideal untuk perpustakaan, sementara itu _bisa_ sangat mengganggu aplikasi. Saya setuju bahwa sistem aplikasi pasti setidaknya dapat menggantikan objek global Promise dan kemudian juga memiliki pengetikan yang cocok untuk kasus penggunaan itu seperti yang tersedia di 2.0.

Pada akhirnya saya berpikir bahwa berdasarkan ideologi TypeScript yang memperluas tipe global Promise harus dilakukan _sangat_ hati-hati (ingat masalah noConflict() dll.) dan jika demikian hanya sebagai keikutsertaan.

IMO cara majunya adalah menulis file bluebird-global.d.ts (atau serupa) yang memperluas objek global Promise dengan deklarasi antarmuka yang sama yang ditemukan di file bluebird.d.ts . Dan jika Anda perlu menggunakannya, Anda harus mengimpornya secara eksplisit alih-alih selalu menyertakannya. Dengan begitu Anda dapat memiliki _dan_ pengetikan yang benar dan aman untuk sebagian besar kasus penggunaan dan terutama saat menulis pustaka, sambil memiliki akses ke manfaat tambahan dari menimpa Promise global dalam aplikasi.

Jika menurut Anda ide ini bagus dan jika Anda memiliki waktu luang yang tersisa, alangkah baiknya jika Anda bisa membuat PR. Saya yakin banyak yang akan sangat senang dengan kontribusi seperti itu. 🙂.

Saya mengatakannya seperti ini karena saat ini saya tidak dalam posisi untuk menulis pengetikan tersebut, karena kurangnya waktu dan tidak membutuhkan pengetikan seperti itu saat ini. Saya harap Anda bisa memahami itu.

@lhecker Saya pikir saya bisa setuju dengan Anda. Karena jika kita memiliki override global dari Promise ke bluebird, kita hanya akan meretas compiler TypeScript, tetapi bukan dunia nyata. Misalnya, dengan Promise Typescript yang ditimpa akan berpikir bahwa fetch mengembalikan yang bluebird:

import `whatwg-fetch`;
let result = fetch("anyurl"); // this is NOT bluebird promise, but typescript think that it is.

Tanpa membungkus fetch ke Promise.resolve bluebird Anda tidak akan mendapatkan, misalnya, metode .finally pada result :

import `whatwg-fetch`;
fetch("anyurl").then().finally() // goes to runtime error with overriden global promise, but should be compile error.

Jadi, saya pikir mengimpor bluebird secara eksplisit pada setiap penggunaan adalah solusi yang lebih baik:

import Promise from "bluebird";
import `whatwg-fetch`;
Promise.resolve(fetch("anyurl")).then().catch() // no compile error, no runtime error

Aku akan refactor kode saya.

Terima kasih atas jawaban Anda, @lhecker .

Saya setuju dengan semua yang Anda katakan. Dan saya suka solusi @Strate untuk membungkus kode pihak ke-3 dengan metode Promise.resolve() , untuk mengubah janji es6 ke Bluebird (atau Bluebird ke Bluebird, karena saya ingin menjaga janji Bluebird secara global saat runtime, jadi saya tidak tidak perlu bergantung pada kode pihak ke-3 untuk menangani kesalahan mereka dengan benar, tapi bukan itu intinya).

Sepertinya saya tidak tahu bagaimana melakukannya dengan benar. Apa yang saya pikir akan bermanfaat bagi orang lain adalah lebih banyak dokumentasi tentang cara menangani masalah ini, karena semua orang yang berasal dari dunia pemrograman browser (berlawanan dengan: dari nodejs/TypeScript) melakukannya setelah mereka:

  1. npm install <absolutely everything that uses es6 promise>
  2. npm install bluebird @types/bluebird
  3. gunakan kode pihak ke-3 dengan TypeScript

Saya juga mendapat manfaat dari memiliki bagian "Cara menggunakan jika kode pihak ketiga diketik dengan es6 Promise" ini didokumentasikan di suatu tempat untuk referensi di masa mendatang. Yaitu memiliki

import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }

dan

import * as Promise from 'bluebird';
import { Observable } from "rxjs";

let observable = Promise.resolve(new Observable<number>().toPromise());

di readme atau di blok doc di bagian atas file bluebird.d.ts.

Bagaimana menurut anda?

Saya telah selesai berpindah dari penggantian global Promise ke bluebird, dan saya menemukan beberapa masalah, di mana perpustakaan pihak ke-3 mengembalikan ES6 Promise, yang dianggap sebagai milik bluebird. Jadi, membuat langkah itu membersihkan basis kode saya juga. Saya akan merekomendasikan kepada semua orang untuk pindah dari kelebihan beban global Promise . Bersulang :)

Saya mengerti modules > globals tetapi katakanlah demi argumen (dan/atau kenyataan) bahwa saya sedang mengerjakan SPA browser besar dan saya telah ditugaskan untuk menggunakan Bluebird sebagai polyfill Janji kami.

Saya mencoba perbaikan bluebird-global.d.ts yang disarankan oleh @lhecker dengan konten dari @d-ph:

import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }

Saya telah menginstalnya melalui typings yang menghasilkan typings/modules/bluebird-global/index.d.ts saya:

// Generated by typings
// Source: src/bluebird-global.d.ts
declare module 'bluebird-global' {
// via https://github.com/DefinitelyTyped/DefinitelyTyped/issues/10801
import * as Bluebird from 'bluebird';
global { export interface Promise<T> extends Bluebird<T> {} }
}

Namun, ketika saya mencoba membangun semuanya, TypeScript (v1.8.2) mengeluh:

ERROR in /path/to/typings/modules/bluebird-global/index.d.ts
(6,27): error TS2665: Module augmentation cannot introduce new names in the top level scope.

ERROR in /path/to/src/bluebird-global.d.ts
(2,35): error TS2665: Module augmentation cannot introduce new names in the top level scope.

Saya melihat contoh MS untuk global-modifying-module.ts
https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html

Dan masalah TS terkait dengan pesan kesalahan ini
https://github.com/Microsoft/TypeScript/issues/6722

Tapi saya bingung dengan apa yang harus saya lakukan. Adakah yang bisa membantu?

Hai.

Bisakah Anda memeriksa repo saya, yang menunjukkan masalah dan solusinya? tautan Saya cukup senang dengan itu, sampai saya memutuskan untuk membungkus semua janji dari pihak ke-3 ke dalam konstruktor Promise bluebird, itulah yang saya lakukan sekarang. Bisakah Anda mengonfirmasi, bahwa setelah Anda mengikuti langkah-langkah di readme, Anda tidak dapat mengkompilasi, tetapi setelah Anda menghapus komentar

// declare global {
//     export interface Promise<T> extends Bluebird<T> {}
// }

itu mengkompilasi?

Perlu diingat, bahwa repo saya menggunakan TS 2 (yang sekarang stabil) dan Anda mengatakan Anda menggunakan 1.8.2. Periksa saja apa yang terjadi, ketika Anda meningkatkan TS ke 2.

Akhirnya, saya memiliki beberapa masalah dengan menempatkan solusi saya di file global d.ts saya. Saya akhirnya menambahkannya ke setiap titik masuk kompilasi webpack saya, yang memecahkan masalah (yang masuk akal bagi saya sekarang). Saya tidak tahu pengaturan js Anda, tetapi dapatkah Anda mencoba menempatkan perbaikan saya di setiap file, yang gagal selama kompilasi (atau setidaknya salah satunya) dan memeriksa apakah itu membantu?

Saya juga ingin dapat "mendaftarkan" implementasi Promise Bluebird sebagai $#$1$# Promise global. Saya membaca seluruh utas ini tetapi saya tidak mengikuti satu bagian. Bagian yang menyarankan bahwa perpustakaan pihak ke-3 masih akan mengembalikan implementasi asli (misalnya non-Bluebird) Promise . Bagaimana ini bisa terjadi, ketika kode pihak ke-3 itu pada suatu saat memanggil konstruktor Promise ( new Promise(...) ) yang telah diganti dengan implementasi Bluebird di tingkat global?

<script src="//.../bluebird.min.js"></script>
<script>
    var promise = fetch("some url");

   promise.finally(...); 
</script>

Bukankah ini akan berfungsi dengan baik karena saya telah menyertakan Bluebird yang telah menggantikan implementasi asli Promise ?

Akhirnya, jika saya melakukan penggantian global penuh ini saat runtime, saya harus dapat memberi tahu TypeScript tentang hal ini sehingga pada waktu kompilasi, semua Janji diganti dengan Bluebird juga.

Apa yang saya lewatkan?

Jika Anda menggunakan versi terjauh dari bluebird (yang Anda lakukan), maka perpustakaan pihak ketiga akan menggunakan Bluebird, karena Janji global sekarang adalah Bluebird. Anda mendapatkan bagian ini dengan benar. Orang-orang menyebutkan sebaliknya, karena mereka berbicara tentang penggunaan node.js dari Bluebird.

Seluruh utas ini adalah tentang cara yang tidak terlalu jelas untuk membuat kompilasi ts dengan asumsi itu (bahwa Janji global adalah Bluebird). Jika Anda berhasil melakukannya (misalnya melalui declare global {} ), maka Anda selesai.

@d-ph Tapi kesimpulan saya adalah saya harus melakukannya di setiap file *.ts bukan hanya sekali -- apakah itu benar? Mungkin ringkasan "solusi" terakhir untuk masalah ini akan bagus. :)

Ya, Anda tahu, tidak ada solusi sederhana just copy&paste this line to your X file and everyone and their dog are happy now di sini. Atau setidaknya aku tidak menyadarinya.

Terakhir kali saya memeriksa Anda:

  1. salin & tempel baris import * as Bluebird from 'bluebird'; declare global { export interface Promise<T> extends Bluebird<T> {} } ke setiap titik masuk file *.ts, atau
  2. bungkus setiap janji yang dikembalikan dari kode pihak ke-3 dalam fungsi konstruktor Bluebird. Dalam runtime itu tidak akan melakukan apa-apa (kecuali untuk overhead runtime yang tidak perlu) dan dalam waktu kompilasi itu akan membuat TS senang.

Sekali lagi, solusi 1. mengharuskan menempatkan kode itu hanya di file titik masuk, tidak setiap file. Setidaknya, inilah yang berhasil bagi saya (webpack + awesome-typescript-loader).

Jika Anda menemukan solusi lain, yang benar-benar mengharuskan pengembang untuk meletakkan hanya 1 baris dalam 1 file, silakan bagikan dengan komunitas ;p

Terima kasih @d-ph -- dapatkah Anda mengonfirmasi apa yang Anda maksud dengan "setiap titik masuk *.ts file"?

Ya. File .ts "Titik masuk" adalah file .ts, yang Anda muat di html Anda melalui tag <script> . Dengan kata lain, ini adalah file dari mana kompilasi dimulai.

Setelah googling cepat barusan, saya menemukan ini (jangan repot-repot membacanya). Intinya adalah, jika Anda menambahkan global { export interface Promise<T> extends Bluebird<T> {} } secara manual di bluebird.d.ts, maka Anda tidak perlu menyebutkan ini lagi di tempat lain. Saya tidak punya waktu untuk mengujinya sekarang, tetapi saya mengujinya dengan repo github pengujian yang saya buat, dan tampaknya berhasil.

Dengan kata lain, unduh bluebird.d.ts dan ubah ini:

// Generated by typings
// Source: bluebird.d.ts
declare module 'bluebird' {
// Type definitions for Bluebird v3.x.x
// Project: http://bluebirdjs.com

class Bluebird<R> implements Bluebird.Thenable<R>, Bluebird.Inspection<R> {

untuk ini:

// Generated by typings
// Source: bluebird.d.ts
declare module 'bluebird' {
// Type definitions for Bluebird v3.x.x
// Project: http://bluebirdjs.com

global { export interface Promise<T> extends Bluebird<T> {} }

class Bluebird<R> implements Bluebird.Thenable<R>, Bluebird.Inspection<R> {

Jelas ini tidak ideal, terutama jika Anda menggunakan @types/bluebird (yang harus Anda hapus sekarang, karena Anda akan menggunakan bluebird.d.ts yang diretas khusus), tapi yah...

Jadi saya sudah memiliki file _stubs.d.ts yang saya tambahkan berikut ini, dan saya jauh lebih dekat. Tidak ada lagi keluhan tentang finally tidak ada pada Promise , tetapi untuk beberapa alasan, saya masih mendapatkan kesalahan tentang delay tidak ada pada Promise . Saya tidak perlu mengedit bluebird.d.ts . Akan menyelidiki tetapi ini mungkin solusi yang bagus!

declare module "bluebird-global" {
    import * as Bluebird from "bluebird";

    global { export interface Promise<T> extends Bluebird<T> { } }
}

Sunting: Masalah saya dengan delay adalah karena saya memanggilnya secara statis, misalnya Promise.delay(2000) .

Dengan solusi yang saya posting di atas, saya mendapatkan kesalahan ini ketika fungsi saya mengembalikan Promise<T> :

kesalahan TS2322: Ketik 'Bluebird' tidak dapat ditugaskan untuk mengetik 'Janji'.

Saya kira ini karena sekarang saya telah mengganti Promise dengan Bluebird , setiap kali saya menggunakan then , dll., nilai yang dikembalikan adalah Bluebird<T> sebagai gantinya dari Promise<T> .

Inilah versi terakhir saya dari peretasan ini. Saya tidak suka melakukan ini tetapi saya menyukainya lebih baik daripada opsi lain. Pada dasarnya, saya harus mengulangi hal-hal yang saya gunakan pada antarmuka, mengubah tipe pengembalian menjadi Promise alih-alih Bluebird . Ini adalah salinan langsung dan tempel dari file definisi Bluebird selain itu.

_stubs.d.ts

declare module "bluebird-global" {
    import * as Bluebird from "bluebird";

    global {
        export interface Promise<T> extends Bluebird<T> {
            then<U1, U2>(onFulfill: (value: T) => U1 | Bluebird.Thenable<U1>, onReject: (error: any) => U2 | Bluebird.Thenable<U2>): Promise<U1 | U2>;
            then<U>(onFulfill: (value: T) => U | Bluebird.Thenable<U>, onReject: (error: any) => U | Bluebird.Thenable<U>): Promise<U>;
            then<U>(onFulfill: (value: T) => U | Bluebird.Thenable<U>): Promise<U>;
            then(): Promise<T>;

            finally<U>(handler: () => U | Bluebird.Thenable<U>): Promise<T>;
        }
    }
}

Akan sangat bagus untuk memiliki definisi resmi bluebird-global atau bluebird-override yang mirip dengan definisi yang ada tetapi menggunakan Promise di mana-mana alih-alih Bluebird .

Senang Anda dapat menemukan solusi.

Hanya untuk kelengkapan: seperti yang dikatakan @ProTip , menggunakan bluebird-2.0.d.ts JustWorksTM. Instal saja dengan npm install @types/[email protected] dan tambahkan ke compilerOptions.types tsconfig.json :

{
    "compilerOptions": {
//     (...)
        "types": [
          "bluebird"
        ]
    },
    "include": [
        "src/**/*.ts"
    ]
}

Setiap perbedaan antara .d.ts dan versi Bluebird saat ini (yaitu 3.x) saya sarankan untuk meretas secara manual.

Maksud saya JustWorksTM: ini berfungsi untuk:

a) target es5
b) sasaran es6
c) target es5 dengan core-js lib

terlepas dari apakah seseorang menggunakan pengaturan build (webpack + awesome-typescript-loader) atau tidak. Selain itu, PhpStorm IDE tidak bingung sama sekali.

Saya menghabiskan beberapa waktu hari ini untuk melihat masalah ini dan pada dasarnya membuat/memperbarui dua tiket itu di Microsoft/TypeScript: https://github.com/Microsoft/TypeScript/issues/10178 dan https://github.com/Microsoft/TypeScript /isu/12382 . Ide saya adalah, seperti yang Anda katakan (dan beberapa sebelum Anda), bahwa kita memerlukan file bluebird-global.d.ts . Untuk menghindari kode duplikat, saya menemukan, bahwa ini akan berhasil:

// bluebird-global.d.ts

import * as Bluebird from "bluebird";

export as namespace Promise;
export = Bluebird;

asalkan dua tiket yang disebutkan di atas diselesaikan atau solusi ditemukan. Sementara itu saya merekomendasikan menggunakan bluebird-2.0.d.ts, ketika coding untuk browser.

@JoshMcCullough

Bagaimana ini bisa terjadi, ketika kode pihak ke-3 itu pada titik tertentu memanggil konstruktor Promise (new Promise(...)) yang telah diganti dengan implementasi Bliebird di tingkat global?

Sangat mudah. Coba di konsol browser Anda (lebih disukai Chrome):

var NativePromise = Promise;
window.Promise = function() {}; // try to overload NativePromise
NativePromise === Promise; // false. Seems it is overloaded!
// And now, let check with some native code, which return Promise, for example fetch
Object.getPrototypeOf(fetch("")) === Promise.prototype; // false, Whoops!
Object.getPrototypeOf(fetch("")) === NativePromise.prototype; // true! Double whoops!

Hai. Saya telah melakukan ini dan itu cukup lancar. Pertama-tama, jangan bergantung pada bluebird untuk proyek perpustakaan. Untuk proyek aplikasi, impor bluebird tetapi bukan pengetikan. Di titik masuk aplikasi Anda, lakukan ini:

global['Janji'] = membutuhkan('bluebird')

Ini akan menggantikan objek janji global untuk aplikasi dan semua perpustakaan yang disertakan.

Hai kawan,

@types/bluebird-global sekarang tersedia. Pengetikan ini menggunakan @types/bluebird@^3.0 di bawah kap mesin dan memungkinkan Anda untuk menggunakan metode bluebird pada Promise global (yaitu kompilasi ts tidak gagal).

Silakan baca ini untuk melihat cara menggunakannya.

Luar biasa, terima kasih @d-ph!

@d-ph Terima kasih atas @types/bluebird-global . Apakah saya perlu melakukan impor dan penugasan ulang dalam proyek saya untuk menggunakan bluebird sebagai pengganti Janji global?

npm install --save-dev @types/bluebird-global dan kemudian ikuti instruksi yang saya sertakan dalam pengetikan: tautan (tautan diperbarui 2017-04-02). Ini saja sudah cukup (yaitu tidak diperlukan impor/penugasan ulang manual).

Sebagai catatan tambahan: Anda tidak perlu lagi menyebutkan @types/bluebird di package.json::devDependencies Anda, karena ini tersirat secara otomatis.

Perbarui ke tautan di komentar sebelumnya: tautan

@MichaelTontchev @d-ph ada kemungkinan kita bisa menambahkan antarmuka Promise.Inspection ke bluebird-global ?

Hai @ksnyde.

Silakan bicara dengan saya. Saya pemeliharanya.

Bisakah Anda mengonfirmasi, bahwa Anda mengacu pada Promise.Inspection ?

Semua metode dari antarmuka itu diekspos melalui bluebird-global . Yaitu yang berikut ini akan dikompilasi:

let promiseInspectionTest = new Promise<void>((resolve) => {});
promiseInspectionTest.value();

Jadi menurut saya, Anda meminta ini diekspos sebagai Promise.Inspection dari bluebird-global .

Bisakah Anda memberi tahu saya, apakah ini merupakan kemunduran besar bagi Anda untuk menggunakan yang berikut ini sebagai gantinya:

import * as Bluebird from "bluebird";

class Foo<T> implements Bluebird.Inspection<T> {

}

Karena Anda menggunakan bluebird-global , Anda juga dapat mengimpor bluebird pengetikan asli seperti itu tanpa devDependencies eksplisit.

Saya lebih suka tidak memperluas Promise global lebih jauh tanpa alasan kuat di baliknya, karena itu adalah seni yang halus untuk membuat pengetikan tersebut bekerja dengan pengetikan Promise standar dari lib.d.ts . Saya sangat merekomendasikan untuk mengakses antarmuka ini dari pengetikan bluebird secara langsung, karena suatu hari ahli JavaScript mungkin menambahkan Promise.Inspection ke standar, yang akan merusak pengetikan bluebird-global , yang akibatnya akan menyebabkan masalah yang tidak perlu bagi pengguna akhir.

Juga, bahkan jika saya ingin menambahkan antarmuka, Anda perlu menunggu waktu yang tidak ditentukan untuk digabungkan menjadi master , karena pengelola DT agak sibuk dengan PR akhir-akhir ini.

Bersulang.

Saya memang telah menggunakan pendekatan yang Anda diskusikan untuk saat ini dan itu adalah pekerjaan yang memadai. Atau mungkin "menyelesaikan" adalah nomenklatur yang salah.

Pemahaman/persepsi saya adalah bahwa ide di balik bluebird-global adalah untuk mengekspos superset fungsi Promise yang disediakan bluebird dalam hal ini sebagai pengguna saya _would_ mengharapkan Bluebird.Inspection diekspos pada Promise.Inspection . Namun, jika maksud Anda lebih untuk memastikan bahwa permukaan API resmi dari Promises menggunakan Bluebird maka saya kira "penyelesaian" ini sebenarnya adalah solusi jangka panjang yang tepat.

Sementara saya lebih suka interpretasi saya, saya akan baik-baik saja menggunakan solusi yang disajikan di sini jika perlu.

Meskipun saya pasti melihat dari mana Anda berasal dengan harapan Anda, alasan utama mengapa saya membuat bluebird-global adalah untuk memberi tahu TypeScript, bahwa Janji yang dibuat dan dikembalikan dari kode pihak ketiga sebenarnya adalah contoh dari janji Bluebird, yang tidak ada alternatif lain yang _tidak mengganggu_, tetapi untuk mengekspos semua instance Bluebird dan metode statis pada simbol Promise global. Seperti yang saya sebutkan sebelumnya, cara melakukannya bukanlah class Promise<T> extends Bluebird<T> {} sederhana (walaupun awalnya), melainkan simbol Janji global yang ditambal dengan hati-hati. Dan seperti yang saya sebutkan, saya lebih suka menghindari keharusan mempertahankan apa pun, karena ada alternatif yang diketahui, yang tidak secara harfiah membuat Anda mencabut rambut Anda.

Maaf untuk mengatakan "Tidak" untuk yang satu ini. Jika ada lebih banyak orang yang meminta fitur khusus ini, saya akan mempertimbangkan kembali untuk menambahkannya. Saya tidak ingin terdengar otoritatif di sini -- ini adalah proyek sumber terbuka dan siapa pun mungkin dapat memasukkan fitur ini. Maksud yang ingin saya sampaikan di sini adalah, menurut pendapat saya, manfaat dari masuknya fitur ini adalah tidak melebihi biaya pemeliharaannya.

Bersulang.

masuk akal. terima kasih atas pemikiran di balik pendekatan Anda.

@d-ph apakah hal berikut ini masuk akal bagi Anda ... Saya mendapatkan pesan kesalahan yang menyatakan bahwa "reflect" bukan fungsi pada kode di bawah ini:

image

Dan sementara di intelisense editor mengidentifikasi dengan benar bahwa properti p dalam fungsi pemetaan adalah janji Bluebird dan memiliki permukaan API yang diperluas hanya ditemukan di Bluebird (versus Promise).

image

Aku hanya tidak bisa membuat kepala atau ekor keluar dari itu. Saya memang memperhatikan bahwa ketika saya memeriksa _type_ dari variabel iterator peta itu muncul sebagai:

image

Saya kira inilah akhirnya mengapa saya mendapatkan permukaan API terbatas yang ditentukan oleh bluebird-global tetapi saya tidak tahu mengapa itu tidak diselesaikan dengan benar.

Hai.

Saya tidak dapat mereproduksi:/ Cuplikan kode itu berfungsi di pengaturan saya.

Pertama. Anda tidak menggunakan bluebird-global dalam fungsi allSettled() Anda. Anda mengetik langsung menggunakan Bluebird . Ini bukan masalah, tapi mungkin Anda tidak menyadarinya. Cuplikan berikut menggunakan bluebird-global :

function allSettled<T>(promises: Array<Promise<T>>) {
    const reflections = Promise.all<T>(promises.map((promise => {
        return promise.reflect();
    })));

    return reflections;
}

Yaitu jenis cuplikan ke Promise global (yang ditambal dengan metode Bluebird di bluebird-global.d.ts ). Seperti yang saya katakan: ini untuk informasi Anda, jika Anda tidak menyadarinya, karena cuplikan Anda dan saya bekerja sama.

Kembali ke masalah hilangnya metode Bluebird. Dugaan saya adalah: Anda tidak mengganti global Promise dengan Bluebird saat runtime dan kemudian Anda menjalankan allSettled() dengan Promises yang dibuat menggunakan Promise global alih-alih Bluebird.

Mari saya tunjukkan kode saya dan beberapa tangkapan layar.

function allSettled<T>(promises: Array<Promise<T>>) {
    const reflections = Promise.all<T>(promises.map((promise => {
        return promise.reflect();
    })));

    return reflections;
}

let promises = [
    Promise.resolve(),
    Promise.reject(new Error("rejected test")),
    new Promise<void>(() => {}),
];

let reflections = allSettled(promises);

console.log(reflections);
// this is part of my entry point

/*
 * Promise
 */
import * as Promise from 'bluebird';
import 'expose-loader?Promise!bluebird';

image
_Pic 1: Janji di Array.map() adalah Bluebird (Anda dapat mengetahui dengan adanya properti garis bawah seperti: _bitField )_

image
_Pic 2: Promise.reflect memang didefinisikan dalam loop_

Bisakah Anda menyetel breakpoint js seperti saya di Chrome Dev Tools, dan melihat apa itu promise di dalam .map ? Lebih baik lagi: bisakah Anda mengetikkan Promise di konsol dan melihat apakah Anda mendapatkan output berikut:
image

Jika Anda mendapatkan output berikut, maka Anda TIDAK mengganti Global Promise dengan Bluebird saat runtime:
image

Dalam hal ini Anda perlu melakukannya. Misalnya seperti saya di file entri Anda.

Akhirnya, hanya sedikit umpan balik pengembang: Saya pribadi akan menggunakan Promise<T>[] alih-alih Array<Promise<T>> . Tapi ini tergantung pada preferensi pengembang tentu saja. Saya baru saja datang dari latar belakang C, di mana tidak ada templating dan di mana pengembang menggunakan operator akses-array untuk menentukan tipe.

Bersulang.

Terima kasih banyak atas penjelasan yang begitu menyeluruh. Satu hal yang saya tidak yakin adalah apa yang ditunjukkan oleh poin berikut:

import 'expose-loader?Janji!bluebird';

@d-ph ahhh, satu liner di atas adalah yang saya lewatkan. Tidak akan pernah sampai di sana tanpa bantuan Anda! Mungkin hanya saya, tetapi saya pikir akan sangat membantu jika teks README memiliki referensi ke penggunaan Expose Loader .

Meskipun adil, saya masih belum 100% jika ini kemudian membutuhkan penggunaan webpack? Target saya bukan browser, hanya fungsi node.

Faktanya, sepertinya itu tidak sepenuhnya berfungsi karena saya mendapatkan kesalahan berikut ketika saya mencoba menjalankan file (tidak ada kesalahan di editor sebelum waktu berjalan):

Kesalahan: Tidak dapat menemukan modul 'expose-loader? Promise!bluebird'

Anda benar, expose-loader adalah hal webpack (pemuat webpack). Jadi jika Anda tidak membiarkan webpack memproses pernyataan import itu, itu tidak akan berjalan (yaitu Anda akan mendapatkan kesalahan "Tidak dapat menemukan modul").

Jika Anda tidak dapat/tidak menggunakan webpack, Anda perlu mencari cara lain untuk membuat Promise global menjadi Bluebird saat runtime. Saya tidak punya banyak pengalaman dengan simpul, tetapi saya baru saja menemukan ini: https://github.com/petkaantonov/bluebird/issues/1026 (mengganti Promise dalam simpul).

Saya sarankan mencari tahu cara menggunakan async/menunggu di node 7. Anda cukup beruntung untuk hidup di masa, ketika ini tersedia untuk devs.

Mengenai menggunakan expose-loader di README: Saya sudah menyatakan di bagian atas file d.ts , bahwa ini adalah tugas pengembang untuk mengganti Promise dengan Bluebird di runtime: link . Karena ada begitu banyak cara untuk melakukannya, saya tidak menyebutkan salah satunya. Perlu diingat, bahwa expose-loader sama dengan menjalankan window.Promise = Bluebird . Yah, semoga google akan mengindeks balasan saya, jadi orang tidak akan mencari opsi yang mungkin terlalu lama lagi ;p

@d-ph menantikan async-await asli tetapi semua fungsi ini ada di AWS Lambda jadi saya terkunci ke node 6.10.x untuk saat ini. Di masa mendatang dari fungsi-fungsi ini, saya mungkin akan beralih ke async-wait dan meminta TypeScript mentranspilenya ke ES2015 tetapi belum ingin memperkenalkan ini dulu.

Bagaimanapun, terima kasih atas tautannya @ d-ph, saya akan mencoba pendekatan itu. Oh dan jika ada yang tertarik dengan versi final dari fungsi-fungsi ini (yang cukup berguna di tanah janji):

export function allSettled<T>(promises: Array<Promise<T>>) {
  const reflections = Promise.all<Promise.Inspection<T>>( promises.map((p => p.reflect())) );
  return reflections as Promise<Array<Promise.Inspection<T>>>;
}

export function settleProps<T>(promiseHash: IDictionary<Promise<T>>) {

  const reflections: IDictionary<Promise<Promise.Inspection<T>>> = Object.keys(promiseHash)
    .reduce((newObject: IDictionary<any>, key: string) => {
      newObject[key] = promiseHash[key].reflect();
      return newObject;
    }, {} as IDictionary<Promise<Promise.Inspection<T>>>);

  return Promise.props(reflections) as Promise<IDictionary<Promise.Inspection<T>>>;
}

Informasi intelisync/type lengkap tersedia yang sangat bagus.

@d-ph semoga tidak apa-apa jika saya menghidupkan kembali ini dengan pertanyaan yang relevan ...

Ketika saya mencoba menggunakan bluebird-global, saya tampaknya mendapatkan sedikit perbedaan definisi di then dan catch . Saya melihat bahwa itu ditangani secara khusus di bluebird-global, tetapi tampaknya membatasi saya pada api Promise standar alih-alih mendapatkan bluebird. Sebagai contoh:

Promise.resolve(true).catch(Error, () => false)

gagal karena catch hanya mengharapkan 1 argumen.

Dan masalah lain:

Promise.resolve([3]).map((n: number) => true)

Gagal dengan:

│TS2345: Argument of type '(n: number) => boolean' is not assignable to parameter of type 'IterateFunction<{}, boolean>'.           │
│  Types of parameters 'n' and 'item' are incompatible.                                                                             │
│    Type '{}' is not assignable to type 'number'.                                                                                  │

Haruskah itu bekerja atau saya melakukan sesuatu yang salah? Mereka bekerja saat runtime, mereka hanya tidak mengetik.

Terima kasih!

Hai,

Tentang .catch(Error, function) , Anda benar dengan mengatakan bahwa .then , .catch (dan lebih banyak lagi) ditangani secara berbeda dari fungsi Bluebird lainnya. Namun, penggantian .catch(Error, function) spesifik disertakan dalam bluebird-global . Saya memeriksa ulang dan saya dapat mengkompilasi:

Promise.resolve(true).catch(Error, () => false)

Saya memeriksa dengan TS 3.0.1 dan 2.9.2. Saya tidak tahu mengapa Anda mungkin mengalami masalah di sini. Mungkin ada sesuatu yang spesifik dalam proyek TS Anda yang mengesampingkan Janji global setelah bluebird-global . Saya tidak tahu. Mungkin mencoba mempersempit apa yang menyebabkan masalah dengan memulai dari proyek TS yang sangat mendasar dan kemudian menambahkan lebih banyak dependensi dari proyek Anda saat ini, dan lihat di titik mana itu rusak.

Tentang masalah lain: Saya tidak tahu mengapa itu tidak berhasil. Dan ya, itu harus berhasil. Silakan buat masalah github untuk itu dan kami akan pergi dari sana. Berikut adalah beberapa fakta tentang masalah tersebut:

  1. Semua yang dilakukan bluebird-global dengan .map() hanyalah menggunakan kembali definisi tipe bluebird.d.ts .map() . Dengan kata lain, cacat seharusnya tidak berasal dari pengetikan bluebird-global .
  2. Baris yang Anda sebutkan gagal pada Promise.map() , tetapi berfungsi pada Bluebird.map() :
import Bluebird = require('bluebird');

Bluebird.resolve([3]).map((n: number) => true); // works

Promise.resolve([3]).map((n: number) => true); // fails
  1. Setelah menghabiskan beberapa waktu untuk mendekripsi masalah TypeScript (pada dasarnya: mengapa TS menyimpulkan bahwa parameter n harus {} ), saya menyimpulkan bahwa bluebird.d.ts juga seharusnya tidak berfungsi, tetapi itu berfungsi untuk alasan yang tidak saya ketahui. Singkat cerita, berikut ini adalah cara mengetik .map() setelah menghapus semua lapisan abstraksi:
map<U>(
    mapper: (
        item: U,
        index: number,
        arrayLength: number
    ) => U | PromiseLike<U>,
    options?: Bluebird.ConcurrencyOption
): Bluebird<T extends Iterable<any> ? U[] : never>;

Dikatakan bahwa tipe pengembalian fungsi mapper harus sama (atau Janji yang sama) dengan tipe item . Dalam contoh Anda, jenis itemnya adalah number dan jenis pengembaliannya adalah boolean . Saya tidak dapat memahami mengapa ini dikompilasi ketika menggunakan Bluebird secara langsung, tetapi tidak ketika menggunakan Global Promise. Omong-omong, itu masih tidak berfungsi, ketika saya mengubah tipe pengembalian dalam contoh Anda menjadi angka apa pun. Namun, itu berhasil, ketika saya mengatakan bahwa item dapat bertipe any . Ada yang salah dengan bluebird.d.ts 's type IterableItem<R> dan penggunaannya dalam konteks ini.

@d-ph


Sunting:

Saya memeriksa formulir "tidak berlapis" map() lagi, dan fungsi mapper tidak diketik untuk memiliki tipe pengembalian yang sama dengan tipe item (saya pikir itu dulu). Salahku.

Semua yang dilakukan bluebird-global dengan .map() hanya menggunakan kembali definisi tipe .map() bluebird.d.ts.

Apakah masalahnya ketika Anda menyalin tipe dari kelas generik Bluebird<R> defaultnya ke {} untuk R karena tidak dapat menyimpulkannya dari induknya?

Saya ingin tahu apakah map: typeof Bluebird<T>.prototype.map akan berhasil? (Saya belum mencoba ini)

PENTING:
Jika menggunakan @types/bluebird-global , hapus formulir dependensi Anda @types/bluebird seperti yang dikatakan oleh @d-ph

npm install --save-dev @types/bluebird-global dan kemudian ikuti instruksi yang saya sertakan dalam pengetikan: tautan (tautan diperbarui 2017-04-02). Ini saja sudah cukup (yaitu tidak diperlukan impor/penugasan ulang manual).

Sebagai catatan tambahan: Anda tidak perlu lagi menyebutkan @types/bluebird di package.json::devDependencies Anda, karena ini tersirat secara otomatis.

Memiliki keduanya menyebabkan ketidakcocokan antara jenis yang dikembalikan oleh @types/bluebird dan Janji global saya ( @types/bluebird-global )

Apakah halaman ini membantu?
0 / 5 - 0 peringkat