مرحبا جميعا!
أنا أستخدم بلوبيرد كبديل لكائن الوعد العالمي. لقد حاولت تحديث ملفات Typedefs إلى أحدث إصدار ، تم نشره بواسطة lhecker ، وواجهت مشكلة: لا يتم تحميل Promsie
العالمي بشكل زائد الآن بشكل افتراضي.
كيف الكاميرا أحقق السلوك السابق؟ ربما يمكن أن يكون لدينا Bluebird-global.d.ts ، على سبيل المثال؟
حسنًا ، IMHO لم تكن تعريفات Bluebird السابقة حلاً جيدًا أيضًا ، لأنها تسربت بشكل كبير إلى مساحة الاسم العالمية وأعتقد أنها كانت فكرة جيدة لتقليل الجهود الزائدة عن الحاجة.
الطريقة التي عملت بها التعريفات السابقة هي تحديد declare var Promise: PromiseConstructor;
بينما PromiseConstructor
كانت واجهة Bluebird السابقة (المحددة عالميًا).
أي إذا قمت بإنشاء ملف *.d.ts
محلي وأضفت شيئًا كهذا ، فربما يعمل؟
import Bluebird = require("bluebird");
declare var Promise: Bluebird<any>;
ربما تعمل ربما؟
للاسف لا. لأن لدي الكثير من التعليمات البرمجية ، والتي تمت كتابتها على النحو التالي:
declare function doLoadData(): Promise<Data>
كما ترى ، ترجع الدالة Promise<T>
، وهو المعيار Promsie
، وليس بلوبيرد. بالإعلان var Promise: Bluebird<any>
سأزيد تحميل مُنشئ Promise القياسي ، وليس الواجهة.
عدت إلى كتابة 2.0 لهذا السبب.
Strate آه لعنة لقد كتبت تعليقًا مطولًا حول ما أفكر فيه حول هذا وما يجب أن نحاول القيام به. لكن يبدو أنني نسيت أن أقدمها وضاعت أخيرًا ...
يبدو أن الكثير من الناس لديهم هذه المشكلة.
لقد أنشأت الريبو الذي يوضح المشكلة: https://github.com/d-ph/typescript-bluebird-as-global-promise
استنساخ git && npm install
&& npm run tsc
المشكلة:
تتم كتابة ملفات الطرف الثالث d.ts
مقابل Promise
. يتم تحديد Promise
هذا إما عن طريق lib.es6.d.ts
الخاص بـ printcript (عندما "target": "es6"
) أو بواسطة libs الأخرى ، على سبيل المثال core-js
(شائع جدًا ، عند التحويل إلى es5 باستخدام الكتابة المطبوعة) . لم يتم الإعلان عن أحدث bluebird.d.ts
على أنه Promise
عالميًا ، على الرغم من أن bluebird.js يعرض نفسه على أنه Promise
عالميًا.
نتيجة:
لا يمكن للمطورين استخدام وظائف بلوبيرد في الوعود التي تم إرجاعها من كود الطرف الثالث (فشل التجميع).
نتيجة متوقعة:
يمكن للمطورين استخدام وظائف بلوبيرد في الوعود التي تم إرجاعها من كود الطرف الثالث (نجح التجميع).
لست متأكدا من هو المشرف على كتابات بلوبيرد. lhecker ، أنت الشخص غير المحظوظ الذي تم إرجاعه git blame
. هل يمكن أن تخبرنا ، ما هو السبب المفضل لاستخدام كتابات بلوبيرد بهذه الطريقة ، أن مشروع جيثب ، الذي ربطته أعلاه ، يجمع؟
جولات المشي الحالية:
Promise
، استخدم هذا: Promise["config"]({}); Promise.resolve("foo")["finally"](() => { console.log("lol"); })
لإسكات المترجم. أي استخدم عامل الوصول إلى الصفيف: [""]
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }
لوظائف Bluebird الثابتة ، استخدم Bluebird.config({})
بدلاً من Promise.config({})
.
الجانب السلبي هو أن IDEs تكافح لتفسير هذا الاختراق بشكل صحيح.
حسنًا ... كان من غير المتوقع بالنسبة لي أن تواجهكم مشاكل مع هذا ، لأنكم جميعًا تستخدمون Bluebird بطريقة لا أفعلها أنا والعديد من الآخرين. في الحقيقة لم أكتب الكتابات بنفسي! لقد قمت ببساطة بنسخ النسخ الموجودة فقط لـ 3.0 من هنا ، لأن وجود أي كتابة لـ 3.0 أفضل من عدم وجود أي كتابة ، أليس كذلك؟
الشيء هو أن الاتجاه الحالي الذي يتجه إليه TypeScript هو modules > globals
وهو أمر أوافق عليه حقًا. ولكن هذا يعني أيضًا أن الوحدات النمطية لا يجب أن تقوم بتعديل الكائنات العامة مطلقًا ، خاصة إذا كنت تعتقد أن Bluebird
لا يحل محل Promise
العالمي في كل حالة! أو لنضعها على هذا النحو:
ماذا يحدث لـ "نوع الأمان" إذا اتصلت بـ Promise.noConflict()
حرفياً في أي مكان في شفرتك؟ سيعيد النوع Promise
العالمي إلى النوع الأصلي وسيؤدي إلى تعطل الكود ، على الرغم من أن tsc
أخبرك أن كل شيء على ما يرام.
لذا نعم ... @ d-ph. الجولة الثانية الخاصة بك هي ما يجب أن تفكر في القيام به طوال الوقت ، لأنه يتماشى مع روح أنظمة الوحدات. لكني أعلم أن هذا هو الحل الأمثل للمكتبات ، في حين أنه _ يمكن أن يكون مزعجًا حقًا للتطبيقات. أوافق على أن أنظمة التطبيقات يجب أن تكون بالتأكيد قادرة على الأقل على استبدال الكائن العالمي Promise
ومن ثم أن يكون لديها أيضًا المطابقات المطابقة لحالة الاستخدام هذه كما كانت متوفرة في الإصدار 2.0.
في النهاية ، أعتقد أنه في ضوء أيديولوجية TypeScript التي توسع النوع العالمي Promise
، يجب أن يتم ذلك بعناية شديدة (تذكر مشكلة noConflict()
وما إلى ذلك) وإذا كان الأمر كذلك فقط عند الاشتراك.
طريقة IMO للمضي قدمًا هي كتابة ملف bluebird-global.d.ts
(أو ما شابه) من نوع ما والذي يمتد إلى كائن Promise
العام مع تعريفات الواجهة نفسها الموجودة في ملف bluebird.d.ts
. وإذا كنت بحاجة إلى استخدام هؤلاء ، فيجب عليك استيرادهم صراحةً بدلاً من تضمينهم دائمًا. بهذه الطريقة يمكنك الحصول على طباعة آمنة وصحيحة لمعظم حالات الاستخدام وخاصة عند كتابة المكتبات ، مع إمكانية الوصول إلى المزايا الإضافية للكتابة فوق التطبيقات العالمية Promise
في التطبيقات.
إذا كنت تعتقد أن هذه الفكرة جيدة وإذا كان لديك بعض وقت الفراغ ، فسيكون من الرائع إذا كان بإمكانك إنشاء علاقات عامة. أنا متأكد من أن الكثيرين سيكونون سعداء حقًا بمثل هذه المساهمة. 🙂
أنا أصيغها بهذه الطريقة لأنني حاليًا لست في وضع يسمح لي بكتابة تلك الكتابة ، بسبب ضيق الوقت ولست بحاجة إلى مثل هذه الكتابة في الوقت الحالي. آمل أن تتمكن من فهم ذلك.
lhecker أعتقد أنني يمكن أن أتفق معك. لأنه إذا كان لدينا تجاوز عالمي لوعد بلوبيرد ، فسنقوم فقط باختراق مترجم الحروف ، ولكن ليس العالم الحقيقي. على سبيل المثال ، مع تجاوز Promise
، سوف تعتقد أن الكتابة على الورق المطبوع عليها fetch
تقوم بإرجاع Bluebird:
import `whatwg-fetch`;
let result = fetch("anyurl"); // this is NOT bluebird promise, but typescript think that it is.
بدون التفاف fetch
إلى بلوبيرد Promise.resolve
لن تحصل ، على سبيل المثال ، .finally
على result
:
import `whatwg-fetch`;
fetch("anyurl").then().finally() // goes to runtime error with overriden global promise, but should be compile error.
لذلك ، أعتقد أن استيراد bluebird
بشكل صريح عند كل استخدام هو الحل الأفضل:
import Promise from "bluebird";
import `whatwg-fetch`;
Promise.resolve(fetch("anyurl")).then().catch() // no compile error, no runtime error
سأقوم بإعادة تشكيل الكود الخاص بي.
شكرا لإجابتك ، lhecker .
أنا أتفق مع كل ما قلته. وأحب حل Strate المتمثل في تغليف كود الطرف الثالث بطريقة Promise.resolve()
، لتحويل وعد es6 إلى Bluebird (أو Bluebird إلى Bluebird ، لأنني أرغب في الحفاظ على وعد Bluebird عالميًا في وقت التشغيل ، لذلك لا أفعل لا داعي للاعتماد على كود طرف ثالث للتعامل مع أخطائهم بشكل صحيح ، ولكن هذا بجانب النقطة).
يبدو أنني لم أكن أعرف كيفية القيام بذلك بشكل صحيح. ما أعتقد أن الآخرين سيستفيدون منه هو المزيد من التوثيق حول كيفية التعامل مع هذه المشكلة ، لأن كل شخص قادم من عالم برمجة المستعرض (على عكس: من nodejs / typecript) يصل إليه بعد أن:
npm install <absolutely everything that uses es6 promise>
npm install bluebird @types/bluebird
سأستفيد أيضًا من الحصول على قسم "كيفية الاستخدام في حالة كتابة رمز جهة خارجية مقابل وعد es6" الموثق في مكان ما للرجوع إليه في المستقبل. أي وجود
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }
و
import * as Promise from 'bluebird';
import { Observable } from "rxjs";
let observable = Promise.resolve(new Observable<number>().toPromise());
في الملف التمهيدي أو في كتلة المستندات أعلى ملف bluebird.d.ts.
ما رأيك؟
لقد أكملت الانتقال من التجاوز العالمي لـ Promise
إلى بلوبيرد ، ووجدت بعض المشكلات ، حيث تقوم مكتبات الطرف الثالث بإرجاع ES6 Promise ، والتي تم تصنيفها على أنها Bluebird. لذا ، يؤدي إجراء هذه الخطوة إلى تنظيف قاعدة الشيفرة الخاصة بي أيضًا. أود أن أوصي الجميع بالانتقال من التحميل الزائد العالمي بمقدار Promise
. هتافات :)
أفهم modules > globals
لكن دعنا نقول من أجل الجدل (و / أو الواقع) أنني أعمل على متصفح SPA كبير الحجم وقد تم تكليفي باستخدام Bluebird باعتباره Promise polyfill.
أحاول إصلاح bluebird-global.d.ts
الذي اقترحه lhecker مع المحتوى من @ d-ph:
import * as Bluebird from 'bluebird';
declare global { export interface Promise<T> extends Bluebird<T> {} }
لقد قمت بتثبيته عبر typings
مما أدى إلى الحصول على typings/modules/bluebird-global/index.d.ts
:
// 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> {} }
}
ومع ذلك ، عندما أحاول بناء كل شيء ، يشكو TypeScript (v1.8.2):
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.
ألقيت نظرة على مثال MS مقابل global-modifying-module.ts
https://www.typescriptlang.org/docs/handbook/decerson-files/templates/global-modifying-module-d-ts.html
ومشكلة TS المتعلقة برسالة الخطأ هذه
https://github.com/Microsoft/TypeScript/issues/6722
لكنني في حيرة مما يجب أن أفعله. هل أستطيع مساعدتك؟
مرحبا.
هل يمكنك التحقق من الريبو الخاص بي ، والذي يوضح المشكلة والحل؟ الارتباط . لقد كنت سعيدًا جدًا بذلك ، حتى قررت أن ألتزم بجميع الوعود من جهة خارجية إلى مُنشئ Bluebird's Promise ، وهو ما أفعله الآن. هل يمكنك التأكيد أنه بعد اتباع الخطوات الموجودة في الملف التمهيدي ، لا يمكنك التحويل البرمجي ، ولكن بعد إلغاء التعليق على ملف
// declare global {
// export interface Promise<T> extends Bluebird<T> {}
// }
يجمع؟
ضع في اعتبارك أن الريبو الخاص بي يستخدم TS 2 (وهو الآن مستقر) وقلت أنك تستخدم 1.8.2. فقط تحقق مما يحدث عند ترقية TS إلى 2.
بشكل عام ، واجهت بعض المشكلات في وضع الحل الخاص بي في ملف d.ts
العالمي الخاص بي. انتهى بي الأمر بإضافته إلى كل نقطة دخول لتجميع حزمة الويب الخاصة بي ، مما أدى إلى حل المشكلة (وهو أمر منطقي بالنسبة لي الآن). لا أعرف إعداد js الخاص بك ، ولكن هل يمكنك محاولة وضع الإصلاح الخاص بي في كل ملف ، والذي فشل أثناء التجميع (أو واحد منهم على الأقل) والتحقق مما إذا كان مفيدًا؟
أريد أيضًا أن أكون قادرًا على "تسجيل" تنفيذ Bluebird Promise
باعتباره Promise
العالمي. قرأت هذا الموضوع بأكمله ولكني لا أتبع جزءًا واحدًا. الجزء الذي يشير إلى أن مكتبات الطرف الثالث ستستمر في إرجاع التنفيذ الأصلي (على سبيل المثال غير Bluebird) Promise
. كيف يمكن أن يكون هذا ، عندما يكون كود الطرف الثالث في مرحلة ما يستدعي المُنشئ Promise
( new Promise(...)
) الذي تم استبداله بتطبيق Bluebird على المستوى العالمي؟
<script src="//.../bluebird.min.js"></script>
<script>
var promise = fetch("some url");
promise.finally(...);
</script>
ألا يجب أن يعمل هذا بشكل جيد لأنني قمت بتضمين Bluebird الذي حل محل التنفيذ الأصلي Promise
؟
أخيرًا ، إذا كنت أقوم بهذا الاستبدال الشامل الكامل في وقت التشغيل ، فيجب أن أكون قادرًا على إبلاغ TypeScript بهذا الأمر حتى يتم استبدال Bluebird أيضًا في وقت الترجمة.
ماذا ينقصني؟
إذا كنت تستخدم إصدار dist من بلوبيرد (وهو ما تفعله) ، فستستخدم مكتبات الجهات الخارجية Bluebird ، نظرًا لأن الوعد العالمي أصبح الآن Bluebird. تحصل على هذا الجزء بشكل صحيح. يذكر الناس خلاف ذلك ، لأنهم يتحدثون عن استخدام node.js لـ Bluebird.
هذا الموضوع برمته يدور حول الطريقة غير الواضحة لجعل الملخصات تتراكم مع هذا الافتراض (أن الوعد العالمي هو Bluebird). إذا تمكنت من القيام بذلك (على سبيل المثال من خلال declare global {}
الشيء) ، تكون قد انتهيت.
@ d-ph لكن الوجبات الجاهزة هي أنني يجب أن أفعل ذلك في كل ملف *.ts
بدلاً من مرة واحدة - هل هذا صحيح؟ ربما يكون من الجيد تلخيص "الحل" النهائي لهذه المشكلة. :)
نعم ، كما ترى ، لا يوجد حل بسيط من النوع just copy&paste this line to your X file and everyone and their dog are happy now
هنا. أو على الأقل لست على علم بذلك.
آخر مرة راجعتك إما:
import * as Bluebird from 'bluebird'; declare global { export interface Promise<T> extends Bluebird<T> {} }
في كل ملف * .ts أومرة أخرى ، يتطلب الحل 1. وضع هذا الرمز في ملفات نقطة الإدخال فقط ، وليس كل ملف. على الأقل ، هذا ما نجح بالنسبة لي (webpack + awesome-typecript-loader).
إذا وجدت حلاً آخر يتطلب حرفياً من المطورين وضع سطر واحد فقط في ملف واحد ، فيرجى مشاركته مع المجتمع ؛ p
شكرًا @ d-ph - هل يمكنك تأكيد ما تقصده بعبارة "كل ملف نقطة دخول * .ts"؟
بلى. ملف "Entry point" .ts هو ملف .ts ، الذي تقوم بتحميله في html عبر علامة <script>
. بمعنى آخر ، هذا هو الملف الذي يبدأ منه التجميع.
بعد البحث السريع في Google الآن ، وجدت هذا (لا تهتم بقراءته). خلاصة القول ، إذا أضفت global { export interface Promise<T> extends Bluebird<T> {} }
يدويًا في bluebird.d.ts ، فلن تحتاج إلى ذكر هذا مرة أخرى في أي مكان آخر. ليس لدي وقت لاختباره في الوقت الحالي ، لكنني قمت باختباره باستخدام اختبار github repo الذي قمت بإنشائه ، ويبدو أنه يعمل.
بمعنى آخر ، قم بتنزيل Bluebird.d.ts وقم بتغيير هذا:
// 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> {
الى هذا:
// 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> {
من الواضح أن هذا ليس مثاليًا ، خاصةً إذا كنت تستخدم @types/bluebird
(والذي ستحتاج إلى إزالته الآن ، لأنك ستستخدم Bluebird.d.ts المخصص) ، ولكن حسنًا ...
إذن لدي بالفعل ملف _stubs.d.ts
أضفت إليه ما يلي ، وأنا أقرب كثيرًا. لا مزيد من الشكاوى حول finally
غير موجود في Promise
، لكن لسبب ما ، ما زلت أتلقى أخطاء حول delay
غير موجودة في Promise
. لم يكن علي تعديل bluebird.d.ts
. سوف تحقق ولكن هذا قد يكون حلا رائعا!
declare module "bluebird-global" {
import * as Bluebird from "bluebird";
global { export interface Promise<T> extends Bluebird<T> { } }
}
تحرير: كانت مشكلتي مع delay
لأنني كنت أتصل به بشكل ثابت ، على سبيل المثال Promise.delay(2000)
.
من خلال الحل الذي نشرته أعلاه ، أتلقى هذا الخطأ عندما ترجع وظيفتي Promise<T>
:
خطأ TS2322: اكتب "بلوبيرد
'غير قابل للتخصيص لكتابة' Promise ".
أعتقد أن هذا لأنني الآن قد استبدلت Promise
بـ Bluebird
، عندما أستخدم then
، وما إلى ذلك ، فإن القيمة المرتجعة هي Bluebird<T>
بدلاً من ذلك من Promise<T>
.
ها هي النسخة الأخيرة من هذا الاختراق. لا أحب القيام بذلك ولكني أحبه أفضل من الخيارات الأخرى. بشكل أساسي ، لا بد لي من إعادة تكرار الأشياء التي أستخدمها على الواجهة ، وتغيير نوع الإرجاع إلى Promise
بدلاً من Bluebird
. هذه نسخة مباشرة ولصق من ملف تعريف Bluebird بخلاف ذلك.
_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>;
}
}
}
سيكون من الرائع أن يكون لديك تعريف رسمي bluebird-global
أو bluebird-override
يشبه إلى حد كبير التعريف الحالي ولكنه يستخدم Promise
في كل مكان بدلاً من Bluebird
.
سعيد لأنك تمكنت من إيجاد حل.
فقط من أجل الاكتمال: كما قال ProTip ، باستخدام JustWorksTM bluebird-2.0.d.ts
. فقط قم بتثبيته بـ npm install @types/[email protected]
وأضفه إلى tsconfig.json compilerOptions.types
:
{
"compilerOptions": {
// (...)
"types": [
"bluebird"
]
},
"include": [
"src/**/*.ts"
]
}
أي اختلافات بين ذلك d.ts وإصدار Bluebird الحالي (أي 3.x) أوصي بالاختراق يدويًا.
بواسطة JustWorksTM أعني: إنه يعمل من أجل:
أ) es5 الهدف
ب) es6 الهدف
ج) الهدف es5 مع core-js lib
بغض النظر عما إذا كان شخص ما يستخدم إعداد البناء (webpack + awesome-typecript-loader) أم لا. بالإضافة إلى ذلك ، لا يتم الخلط بين PhpStorm IDE على الإطلاق.
لقد قضيت بعض الوقت اليوم في النظر في هذه المشكلة ، وفي الواقع قمت بإنشاء / تحديث هاتين التذكرة في Microsoft / TypeScript: https://github.com/Microsoft/TypeScript/issues/10178 و https://github.com/Microsoft/TypeScript / قضايا / 12382 . فكرتي هي ، كما قلت (والبعض قبلك) ، أننا بحاجة إلى ملف bluebird-global.d.ts
. لتجنب تكرار الكود ، وجدت أن هذا سيعمل:
// bluebird-global.d.ts
import * as Bluebird from "bluebird";
export as namespace Promise;
export = Bluebird;
شريطة حل التذكرتين المذكورتين أعلاه أو العثور على حلول بديلة. في غضون ذلك ، أوصي باستخدام Bluebird-2.0.d.ts ، عند الترميز للمتصفح.
تضمين التغريدة
كيف يمكن أن يكون هذا ، عندما يكون كود الطرف الثالث في مرحلة ما يستدعي مُنشئ الوعد (الوعد الجديد (...)) الذي تم استبداله بتنفيذ Bliebird على المستوى العالمي؟
سهل جدا. جرب في وحدة تحكم المتصفح (يفضل 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!
مرحبا. لقد كنت أفعل هذا وهو سلس جدًا. بادئ ذي بدء ، لا تعتمد على بلوبيرد في مشروعات المكتبة. بالنسبة لمشروع التطبيق ، قم باستيراد بلوبيرد ولكن ليس الكتابة. عند نقطة دخول طلبك ، قم بما يلي:
global ['Promise'] = يتطلب ('bluebird')
سيحل هذا محل كائن الوعد العالمي للتطبيق وجميع المكتبات المضمنة.
أهلا يا أصدقاء،
@types/bluebird-global
متاح الآن. تستخدم هذه الكتابة @types/bluebird@^3.0
تحت غطاء محرك السيارة وتسمح لك باستخدام أساليب Bluebird على Promise
العالمية (أي أن تجميع TS لا يفشل).
يرجى قراءة هذا لمعرفة كيفية استخدامه.
رائع ، شكرًا @ d-ph!
@ d-ph شكرًا على @types/bluebird-global
. هل أحتاج إلى القيام بأي نوع من الاستيراد وإعادة التعيين في مشروعي لاستخدام بلوبيرد كبديل للوعد العالمي؟
npm install --save-dev @types/bluebird-global
ثم اتبع التعليمات التي قمت بتضمينها في الكتابة: الرابط (تم تحديث الرابط 2017-04-02). هذا وحده من شأنه أن يفي بالغرض (على سبيل المثال ، يجب عدم الحاجة إلى عمليات استيراد / إعادة تعيين يدوية).
كملاحظة جانبية: لست بحاجة إلى ذكر @types/bluebird
في package.json::devDependencies
بعد الآن ، لأن هذا يعني ضمنيًا تلقائيًا.
تحديث للربط في التعليق السابق: رابط
MichaelTontchev @ d-ph هل هناك فرصة للحصول على واجهة Promise.Inspection
المضافة إلى Bluebird-global ؟
مرحبًاksnyde.
يرجى التحدث معي. أنا المشرف.
هل يمكن أن تؤكد أنك تشير إلى هذا الوعد ، فهل تريد الفحص؟
يتم عرض جميع الطرق من تلك الواجهة عبر bluebird-global
. أي ما يلي سيتم تجميعه:
let promiseInspectionTest = new Promise<void>((resolve) => {});
promiseInspectionTest.value();
لذلك يبدو لي أنك تطلب كشف هذا على أنه Promise.Inspection
من bluebird-global
.
هل يمكن أن تخبرني ، ما إذا كانت هذه نكسة كبيرة بالنسبة لك لاستخدام ما يلي بدلاً من ذلك:
import * as Bluebird from "bluebird";
class Foo<T> implements Bluebird.Inspection<T> {
}
نظرًا لأنك تستخدم bluebird-global
، يمكنك أيضًا استيراد الكتابة الأصلية bluebird
بهذا الشكل بدون أي devDependencies
صريح.
أفضل عدم تمديد Promise
العالمي أكثر من ذلك بدون أسباب قوية وراء ذلك ، لأنه فن دقيق لجعل تلك الكتابة تعمل مع كتابة الوعد القياسية من lib.d.ts
. أوصي حقًا بالوصول إلى هذه الواجهة من كتابات bluebird
مباشرة ، لأن معلمي JavaScripts في يوم من الأيام قد يضيفون Promise.Inspection
إلى المعيار ، مما قد يؤدي إلى كسر الكتابة bluebird-global
، مما يؤدي إلى يسبب مشاكل غير ضرورية للمستخدمين النهائيين.
أيضًا ، حتى إذا كنت سأضيف الواجهة ، فستحتاج إلى الانتظار مقدارًا غير محدد من الوقت حتى يتم دمجها في master
، لأن مشرفين DT مشغولون نوعًا ما مع العلاقات العامة هذه الأيام.
هتافات.
لقد كنت بالفعل أستخدم النهج الذي ناقشته في الوقت الحالي وهو عمل مناسب. أو ربما يكون "حل بديل" هو التسمية الخاطئة.
كنت أفهم / تصوري أن الفكرة وراء بلوبيرد جلوبال كانت الكشف عن مجموعة شاملة من وظائف الوعد التي يوفرها بلوبيرد في هذه الحالة كمستخدم أتوقع أن يتم الكشف عن Bluebird.Inspection
عند Promise.Inspection
. ومع ذلك ، إذا كان هدفك هو التأكد من أن سطح API الرسمي لـ Promises يستخدم Bluebird ، فأعتقد أن هذا "الحل البديل" هو في الواقع حل مناسب طويل المدى.
بينما أفضل تفسيري سأكون بخير باستخدام الحل المقدم هنا إذا لزم الأمر.
بينما أرى بالتأكيد من أين أتيت بتوقعاتك ، فإن السبب الرئيسي وراء إنشاء bluebird-global
هو السماح لـ TypeScript بمعرفة ، أن الوعود التي تم إنشاؤها وإعادتها من كود طرف ثالث هي في الواقع أمثلة على وعود Bluebird ، والتي لم يكن هناك بديل آخر _ ليس مزعجًا_ ، ولكن لفضح كل مثيل Bluebird وطرقه الثابتة على رمز الوعد العالمي. كما ذكرت سابقًا ، فإن الطريقة التي يتم بها ذلك ليست بسيطة class Promise<T> extends Bluebird<T> {}
(على الرغم من أنها كانت في الأصل) ، ولكنها بالأحرى رمز وعد عالمي مصحح بعناية. وكما ذكرت ، أفضل تجنب الاضطرار إلى الاحتفاظ بأي شيء ، يوجد بديل معروف له ، لا يجعلك حرفيًا تشد شعرك من رأسك.
آسف لقول "لا" لهذا. إذا كان هناك المزيد من الأشخاص الذين يطلبون هذه الميزة بالذات ، فسأعيد النظر في إضافتها. لا أريد أن أبدو موثوقًا هنا - هذا مشروع مفتوح المصدر ويمكن لأي شخص على الأرجح دفع هذه الميزة فيه. النقطة التي أحاول الوصول إليها هنا هي ، في رأيي ، فائدة الحصول على هذا في لا تفوق تكلفة صيانتها.
هتافات.
من المنطقي. شكرا على التفكير وراء نهجك.
@ d-ph يفعل ما يلي أي معنى بالنسبة لك ... أتلقى خطأ يفيد بأن "عكس" ليس وظيفة في الكود أدناه:
وأثناء وجوده في intelisense للمحرر ، فإنه يحدد بشكل صحيح أن الخاصية p
في وظيفة التعيين هي وعد Bluebird ولديها سطح API ممتد لا يوجد إلا في Bluebird (مقابل Promise).
أنا فقط لا أستطيع إخراج الرؤوس أو ذيولها. لقد لاحظت أنه عندما قمت بفحص _type_ لمتغير مكرر الخريطة ، فإنه يظهر على النحو التالي:
افترضت أن هذا هو سبب حصولي على سطح API المحدود المحدد بواسطة bluebird-global
لكنني لا أعرف لماذا لا يتم حله بشكل صحيح.
مرحبا.
لا يمكنني إعادة الإنتاج: / تعمل مقتطفات الشفرة هذه في الإعداد الخاص بي.
أولا. أنت لا تستخدم bluebird-global
في دالة allSettled()
. تكتب مباشرةً باستخدام Bluebird
. هذه ليست مشكلة ، لكن ربما لم تكن على علم بها. يستخدم المقتطف التالي bluebird-global
:
function allSettled<T>(promises: Array<Promise<T>>) {
const reflections = Promise.all<T>(promises.map((promise => {
return promise.reflect();
})));
return reflections;
}
أي أن هذا المقتطف ينتقل إلى Promise
العالمي (والذي تم تصحيحه باستخدام أساليب Bluebird في bluebird-global.d.ts
). كما قلت: هذا لمعلوماتك ، في حال لم تكن على علم به ، لأن مقتطفاتك ومقتطفاتي تعملان بنفس الطريقة.
لنعد إلى مشكلة فقدان أساليب Bluebird. تخميني هو: لا يمكنك استبدال Promise
العالمي بـ Bluebird في وقت التشغيل ثم تقوم بتشغيل allSettled()
مع الوعود التي تم إنشاؤها باستخدام الوعد العالمي بدلاً من Bluebird.
اسمحوا لي أن أريكم الكود الخاص بي وبعض لقطات الشاشة.
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';
_Pic 1: الوعد في Array.map () هو Bluebird (يمكنك معرفة ذلك من خلال وجود خصائص الشرطة السفلية مثل: _bitField
) _
_Pic 2: الوعد. انعكاس محدد بالفعل في الحلقة_
هل يمكنك تعيين نقطة توقف js مثلي في Chrome Dev Tools ، ومعرفة ما هو promise
داخل .map
؟ الأفضل من ذلك: هل يمكنك كتابة Promise
في وحدة التحكم ومعرفة ما إذا كنت ستحصل على الناتج التالي:
إذا حصلت على الناتج التالي ، فلن تستبدل Global Promise بـ Bluebird في وقت التشغيل:
في هذه الحالة عليك القيام بذلك. على سبيل المثال مثلي في ملف الدخول الخاص بك.
أخيرًا ، القليل من تعليقات المطورين: سأستخدم شخصيًا Promise<T>[]
بدلاً من Array<Promise<T>>
. لكن هذا يرجع إلى تفضيل المطورين بالطبع. لقد جئت للتو من خلفية C ، حيث لا يوجد قالب وحيث يستخدم المطورون عامل الوصول إلى الصفيف لتحديد الأنواع.
هتافات.
شكرا جزيلا لمثل هذا الشرح الشامل. هناك شيء واحد لم أكن متأكدًا منه رغم ذلك وهو ما الذي تشير إليه النقطة التالية:
استيراد "كشف محمل؟ وعد! بلوبيرد" ؛
@ d-ph ahhh ، كانت الخطوط الملاحية المنتظمة أعلاه هي ما كنت في عداد المفقودين. ما كنت لأصل إلى هناك بدون مساعدتك! قد أكون أنا فقط ولكني أعتقد أنه سيكون من المفيد إذا كان النص README
يشير إلى استخدام Expose Loader .
على الرغم من أن نكون منصفين ، إلا أنني ما زلت لست 100٪ إذا كان هذا يتطلب استخدام حزمة الويب؟ هدفي ليس المتصفح ، بل مجرد وظيفة عقدة.
في الواقع ، يبدو أنه لا يعمل بشكل كامل لأنني أتلقى الخطأ التالي عندما أحاول تنفيذ الملف (لا توجد أخطاء في المحرر قبل وقت التشغيل):
خطأ: لا يمكن العثور على الوحدة النمطية "expose-loader؟ Promise! bluebird"
أنت محق ، expose-loader
شيء webpack (محمل webpack). لذلك إذا لم تدع حزمة الويب تعالج عبارة import
، فلن يتم تشغيلها (على سبيل المثال ، ستحصل على الخطأ "لا يمكن العثور على وحدة").
إذا كنت لا تستطيع / لا تستخدم حزمة الويب ، فستحتاج إلى إيجاد طريقة أخرى لجعل الوعد العالمي يكون بلوبيرد في وقت التشغيل. ليس لدي خبرة كبيرة مع العقدة ، لكنني وجدت هذا الآن: https://github.com/petkaantonov/bluebird/issues/1026 (تجاوز Promise
في العقدة).
أوصي بمعرفة كيفية استخدام عدم التزامن / انتظار في أحدث عقدة 7. أنت محظوظ بما يكفي للعيش في الأوقات ، عندما يكون هذا متاحًا للمطورين.
فيما يتعلق بذكر استخدام expose-loader
في README: لقد ذكرت بالفعل في الجزء العلوي من ملف d.ts
، أن هذه مهمة devs لاستبدال Promise بـ Bluebird في وقت التشغيل: link . نظرًا لوجود العديد من الطرق للقيام بذلك ، لم أذكر أيًا منها في الواقع. ضع في اعتبارك أن expose-loader
ما يعادل فقط تشغيل window.Promise = Bluebird
. حسنًا ، آمل أن يقوم Google بفهرسة ردي ، لذلك لن يبحث الناس عن الخيارات الممكنة لفترة طويلة بعد الآن ؛ ص
@ d-ph يتطلع إلى الانتظار غير المتزامن الأصلي ولكن كل هذه الوظائف موجودة على AWS Lambda لذا فأنا مقفل على العقدة 6.10.x في الوقت الحالي. في تمرير مستقبلي لهذه الوظائف ، من المحتمل أن أقوم بالتبديل إلى غير متزامن في انتظار على أي حال ولدي نسخة مطبوعة من الكتابة إلى ES2015 ولكن لا أريد تقديم هذا حتى الآن.
على أي حال ، شكرًا على الرابط @ d-ph ، سأجرب هذا النهج. أوه ، وفي حال كان أي شخص مهتمًا بالنسخة النهائية من هذه الوظائف (والتي تعد مفيدة جدًا في أرض الوعد):
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>>>;
}
تتوفر معلومات كاملة من نوع intelisync وهو أمر رائع للغاية.
@ d-ph آمل أن يكون الأمر على ما يرام إذا أحيت هذا بسؤال ذي صلة ...
عندما أحاول استخدام بلوبيرد جلوبال ، يبدو أنني أتعرض لبعض الاختلافات في التعريف في كل من then
و catch
. أرى أنه يتم التعامل مع هؤلاء بشكل خاص في Bluebird-global ، ولكن يبدو أنه يقصرني على Promise api القياسي بدلاً من الحصول على بلوبيرد. فمثلا:
Promise.resolve(true).catch(Error, () => false)
فشل نظرًا لأن catch
يتوقع وسيطة واحدة فقط.
ومسألة أخرى:
Promise.resolve([3]).map((n: number) => true)
فشل مع:
│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'. │
هل يجب أن يعمل هؤلاء أم أفعل شيئًا خاطئًا؟ إنهم يعملون في وقت التشغيل ، ولا يقومون بفحص الكتابة.
شكرا!
مرحبا،
حول .catch(Error, function)
، أنت محق بقولك أن .then
، .catch
(وأكثر) يتم التعامل معها بشكل مختلف عن باقي وظائف Bluebird. ومع ذلك ، يتم تضمين تجاوز .catch(Error, function)
المحدد في بلوبيرد جلوبال. لقد راجعت مرة أخرى وأنا قادر على تجميع:
Promise.resolve(true).catch(Error, () => false)
راجعت مع TS 3.0.1 و 2.9.2. لا أعرف لماذا قد تواجه مشكلة هنا. ربما هناك شيء محدد في مشروع TS الخاص بك يتجاوز الوعد العالمي بعد bluebird-global
. انا لا اعرف. ربما تحاول تضييق نطاق سبب المشكلة من خلال البدء من مشروع TS أساسي جدًا ثم إضافة المزيد من التبعيات من مشروعك الحالي ، ومعرفة النقطة التي تنقطع فيها.
حول المشكلة الأخرى: لا أعرف لماذا لا يعمل. ونعم ، يجب أن يعمل. الرجاء إنشاء مشكلة github لذلك وسنبدأ من هناك. فيما يلي بعض الحقائق عن المشكلة:
bluebird-global
مع .map()
يعيد استخدام تعريف النوع bluebird.d.ts
.map()
. بمعنى آخر ، لا ينبغي أن يأتي العيب من كتابات bluebird-global
.Promise.map()
، لكنه يعمل على Bluebird.map()
:import Bluebird = require('bluebird');
Bluebird.resolve([3]).map((n: number) => true); // works
Promise.resolve([3]).map((n: number) => true); // fails
n
يجب أن تكون {}
) ، استنتجت أن bluebird.d.ts
أيضًا لا يجب أن تعمل ، لكنها تعمل لسبب غير معروف بالنسبة لي. قصة قصيرة طويلة ، ما يلي هو ما تمت كتابة .map()
إليه بعد إزالة جميع طبقات التجريد:map<U>(
mapper: (
item: U,
index: number,
arrayLength: number
) => U | PromiseLike<U>,
options?: Bluebird.ConcurrencyOption
): Bluebird<T extends Iterable<any> ? U[] : never>;
تقول أن نوع الإرجاع للوظيفة mapper
يجب أن يكون هو نفسه (أو وعد من نفس النوع) مثل نوع item
. في المثال الخاص بك ، نوع العنصر هو number
ونوع الإرجاع هو boolean
. أنا غير قادر على فهم سبب هذا التحويل البرمجي عند استخدام Bluebird
مباشرة ، لكنه لا يحدث عند استخدام الوعد العالمي. بالمناسبة ، ما زال لا يعمل ، عندما أقوم بتغيير نوع الإرجاع في مثالك ليكون أي رقم. ومع ذلك ، فإنه يعمل عندما أقول أن item
يمكن أن يكون من النوع any
. هناك خطأ ما في bluebird.d.ts
type IterableItem<R>
واستخدامه في هذا السياق.
@ د-ف
تعديل:
تحققت من نموذج map()
"بدون طبقات" مرة أخرى ، ولم تتم كتابة الوظيفة mapper
للحصول على نفس نوع الإرجاع مثل نوع item
(اعتقدت ذلك كنت). خطأي.
كل ما يفعله bluebird-global مع .map () هو إعادة استخدام تعريف نوع map () الخاص بـ bluebird.d.ts.
هل المشكلة هي أنه عند نسخ النوع من الفئة العامة Bluebird<R>
، يتم تعيينه افتراضيًا على {}
لـ R
لأنه لا يمكنه الاستدلال عليه من الوالد؟
أتساءل ما إذا كان map: typeof Bluebird<T>.prototype.map
سيعمل؟ (لم أجرب هذا بعد)
الأهمية:
إذا كنت تستخدم @types/bluebird-global
، فاحذف النموذج @types/bluebird
كما قال @ d-ph
npm install --save-dev @types/bluebird-global
ثم اتبع التعليمات التي قمت بتضمينها في الكتابة: الرابط (تم تحديث الرابط في 2017-04-02). هذا وحده من شأنه أن يفي بالغرض (على سبيل المثال ، يجب عدم الحاجة إلى عمليات استيراد / إعادة تعيين يدوية).كملاحظة جانبية: لست بحاجة إلى ذكر
@types/bluebird
فيpackage.json::devDependencies
بعد الآن ، لأن هذا يعني ضمنيًا تلقائيًا.
تسبب كلاهما في حدوث تطابق خاطئ بين الأنواع التي تعود @types/bluebird
ووعدي العالمي ( @types/bluebird-global
)
التعليق الأكثر فائدة
أهلا يا أصدقاء،
@types/bluebird-global
متاح الآن. تستخدم هذه الكتابة@types/bluebird@^3.0
تحت غطاء محرك السيارة وتسمح لك باستخدام أساليب Bluebird علىPromise
العالمية (أي أن تجميع TS لا يفشل).يرجى قراءة هذا لمعرفة كيفية استخدامه.