Mongoose: Возможность указать, какую библиотеку обещаний ES6 использует мангуст.

Созданный на 17 февр. 2015  ·  45Комментарии  ·  Источник: Automattic/mongoose

Смотрите обсуждение #1699

Самый полезный комментарий

Yup require('mongoose').Promise = global.Promise заставит мангуста использовать нативные промисы. Вы должны иметь возможность использовать любой конструктор промисов ES6, но сейчас мы тестируем только нативные, bluebird и Q.

Все 45 Комментарий

Действительно с нетерпением жду возможности использовать Promise.all(), чтобы что-то сделать после того, как вся работа с базой данных будет выполнена.

:+1:

Одна вещь, которая была не очень ясна на https://github.com/LearnBoost/mongoose/issues/1699 , это то, какая реализация будет использоваться по умолчанию.

Хорошо, учитывая, что это не предыдущая версия, mpromise должен быть по умолчанию, но вы сможете его переопределить.

+1

:+1:

Есть ли ветка, где это взламывается? Я не выношу процесс обработки ошибок с помощью mpromise и собираюсь взломать исходный код, чтобы посмотреть, что для этого потребуется.

обещаю:

  query.exec()
    .then(function(ou) {
      if(!ou) {
        return next(new errors.http.NotFound('The specified OU was either not found, or your credentials lack the required permissions to view it.'));
      }

      res.send(ou);
    }, next)
    .end(next);

Придется обработать отказ, а также положить туда end . Без end исключения (например, у меня был класс NotFound с ошибкой) молча проглатываются и выражают просто киоски.

синяя птица:

  query.exec()
    .then(function(ou) {
      if(!ou) {
        return next(new errors.http.NotFound('The specified OU was either not found, or your credentials lack the required permissions to view it.'));
      }

      res.send(ou);
    })
    .catch(next);

Выполнение promisifyAll(require('mongoose')) , похоже, до сих пор работает с Mongoose 4. Не будут ли регрессионные тесты, охватывающие это, слишком целенаправленными?

Не в данный момент. Большая часть работы будет выполняться в модуле kareem в соответствии с #2754 и vkarpov15/kareem#2, потому что это позволит нам убить двух зайцев одним выстрелом и удалить действительно грязную чепуху, которая была написана, чтобы делать крючки и обещания. работать вместе. Не стесняйтесь попробовать, я открыт для пиара.

Но почему мы должны поддерживать поддержку других библиотек промисов? Спецификация ES6 Promises теперь надежна и никуда не денется. Разве мы не можем просто использовать чистые обещания ES6 с загруженным полифиллом, когда они недоступны в более старых версиях узла?

Если да, то могу попробовать.

Дело в том, что вы сможете использовать любую библиотеку обещаний, совместимую с ES6, которая вам нравится. Многие люди по-прежнему вкладывают большие средства в bluebird, когда, q, rsvp и т. д. и т. д., и каждая из этих библиотек имеет свои особенности, которые не будет охватывать общий полифилл.

Я открыт для альтернативных предложений - мне не особенно нравятся промисы и я не использую их, эта функция мотивирована тем фактом, что есть масса вопросов, связанных с людьми, которые просят "поддержать функцию bluebird X в mpromise" или "нативную поддержку rsvp.js". "и позволить людям приносить на вечеринку свою собственную библиотеку обещаний - это самый простой способ закрыть эти проблемы.

Я понимаю, что вы имеете ввиду. Я большой пользователь и сторонник Promises. Я думаю, что это следует рассмотреть для обеспечения соблюдения стандарта.
Обещания A+ были выбраны в качестве основы для ES6. Я предложил полифилл, чтобы обеспечить поддержку несовместимых с ES6 версий узлов (например, https://github.com/jakearchibald/es6-promise).

Она должна быть в руках другой библиотеки промисов, чтобы быть совместимой и смешиваемой с промисами ES6.

РЕДАКТИРОВАТЬ:
И не было бы поломки текущего API или я что-то упускаю?

Спецификация Promises/A+ сильно отличается от спецификации промисов ES6, которая, в свою очередь, отличается от библиотек промисов, которые я перечислил в предыдущих комментариях. Хотя для меня было бы хорошо, если бы все бесчисленные библиотеки обещаний были объединены в ES6, я сомневаюсь, что это когда-либо произойдет, потому что красота открытого исходного кода заключается в том, что некоторые люди, которые любят обещания, захотят дополнительные функции и будут писать свои собственные обещания. библиотеки.

Никаких критических изменений для текущего API, я думаю, это способ сказать mongoose.set('Promise', require('bluebird')); или что-то в этом роде, так что это будет согласие, а mpromise будет по умолчанию.

Ах да, извините за эту ошибку.
Я взглянул на текущую реализацию и другую библиотеку обещаний.

Я думаю, что могу сделать что-то вроде этой работы:

mongoose.set('Promise', Promise);

mongoose.set('Promise', require('bluebird'));

mongoose.set('Promise', require('q').defer());

mongoose.set('Promise', require('when').defer());

// and so on...

Таким образом, вы должны предоставить Mongoose объект обещания выбора, который имеет методы resolve и reject .

Это было бы то, что вы имели в виду? Если да, то я буду работать над запросом на вытягивание.

РЕДАКТИРОВАТЬ:
Очень глупо писать mongoose.set('Promise', Promise); . Я думаю, что ES6 должен быть по умолчанию, с возможностью использовать вашу библиотеку по выбору (и mpromise, когда обещания ES6 недоступны).

Конечно, я был бы признателен за вашу помощь. Хитростью будет 1) заставить его работать с хуками - см. vkarpov15/kareem#2, и 2) сделать его обратно совместимым с mpromise.

Кроме того, в отношении Q мы будем использовать require('q').Promise , так как этот синтаксис Q наиболее близок к спецификации ES6.

Спасибо за ваш вклад, будем работать над этим. Что вы предпочитаете: пулл-реквест или постоянный PR?

Завершенный лучше, но у меня всегда будут некоторые предложения. Дайте мне знать, если вы застряли

+1 за эту функцию. я хотел бы использовать с bluebird

Извините за резкость, но альтернативным подходом было бы полное прекращение поддержки обещаний. Это заставило бы заткнуться любого, кто использует обещания, запрашивающие поддержку других библиотек.
Люди, использующие мощные библиотеки промисов, такие как bluebird, могут продолжать использовать его в любом случае, поскольку вы предоставляете API обратного вызова, а bluebird может тривиально обернуть его с нулевой стоимостью - на самом деле есть вероятность, что, поскольку вы не знаете или не используете промисы (как вы сказали), шансы в любом случае это будет медленнее и больше подвержено ошибкам, чтобы поддерживать их вручную.

@benjamingr 100% не согласен. Теперь, когда iojs и NodeJs объединяются в Node 3.0, появится поддержка промисов и генераторов ES6.

Отказ от поддержки был бы огромным шагом назад.

То есть Promise.promisifyAll(require("mongoose")) создает быструю (быстрее, чем любые вероятные ручные попытки) оболочку для Mongoose, которая соответствует стандартам и окружает весь API, и вам не нужно ничего с этим делать. На самом деле, вы можете сами сделать Promise.promisifyAll для объекта экспорта и бесплатно предоставить промисы bluebird и метод двойных промисов (save - saveAsync) , а затем сказать, что вы предоставляете интерфейс промисов bluebird без необходимости выполнять какую-либо реальную работу.

Итак, хотя я сам использую промисы bluebird, я думаю, что все это можно исправить в разделе документации, а не усложнять код, кодируя два интерфейса.

@albertorestifo, за исключением того, что на самом деле ничего не будет удалено. Я очень хорошо знаю, что такое промисы (более 1500 баллов и 500 ответов в переполнении стека :P), и я даже отвечаю за некоторые части того, как они работают в io.js (например, https://github.com/ nodejs/io.js/issues/256).

Это не меняет того факта, что я считаю, что, поскольку @vkarpov15 не использует промисы, ему не нужно поддерживать их в своей библиотеке, тем более, что в любом случае это не дает никаких преимуществ по сравнению с использованием промисов с ним_. Вы можете использовать промисы с мангустом так же легко, даже если он их не предоставляет - мангуст, реализующий внутреннюю поддержку, больше поддерживает, вероятно, медленнее и более подвержен ошибкам. @vkarpov15 может продолжить работу над API обратного вызова и обещает, что пользователи все равно смогут обернуть Mongoose промисами одним простым вкладышем.

@benjamingr предполагает, что кто-то использует внешнюю библиотеку Promise. Я придерживаюсь того, что указано в спецификациях, и вы прекрасно знаете, что у него нет оболочки.

Я вижу вашу точку зрения. Поддержка обоих создает огромный беспорядок. Я лично презираю обратные вызовы, поэтому я бы отказался от них. Возможно, должно быть два отдельных репозитория, один с использованием генераторов и промисов, а другой с обратными вызовами. Оба будут поддерживать одинаковую структуру и максимально близкий API.

@benjamingr предполагает, что кто-то использует внешнюю библиотеку Promise. Я придерживаюсь того, что указано в спецификациях, и вы прекрасно знаете, что у него нет оболочки.

Если вы решите использовать медленную, сложную в отладке и менее многофункциональную реализацию, это, конечно, ваш выбор: P, но как это связано с оболочкой? Совершенно несложно написать оболочку, подобную promisifyAll в bluebird, используя собственные промисы*.

Если вам нужна версия Mongoose с поддержкой обещаний в виде отдельного пакета, вот как вы можете это сделать:

  • Шаг 1. Откройте свой любимый редактор или просто редактор, который вам нравится.
  • Шаг 2, введите module.exports = require("bluebird").promisifyAll(require("mongoose"))
  • Шаг 3, создайте соответствующий файл package.json , опубликуйте в npm
  • Шаг 4, десятки тысяч загрузок.

Теперь я знаю, о чем вы думаете: «Это не использует нативные промисы», но вы все равно можете удалить все методы, кроме then и catch из прототипа промиса и all и race из Promise и в конечном итоге с одним и тем же API — или вы можете просто сказать людям, что вы экспортируете нативные промисы — они не узнают, так как это всего лишь две реализации Promises/A+, Я обещаю ;)

(*написать это быстро на пользовательском уровне сложнее, потому что сейчас нет быстрого способа создавать промисы, поэтому io.js, скорее всего, в конечном итоге экспортирует саму функцию обещания - это говорит о том, что вы берете конструктор промисов, который вы заставляете его в любом случае помедленнее).

Это определенно достойная альтернатива. Тем не менее, я хотел бы сдержать обещания внутри компании, потому что, нравится вам это или нет, пользователи будут использовать mongoose именно так, поэтому у нас также может быть надежное тестовое покрытие для него, чтобы мы могли указать и сказать: «Вот как вы используете библиотеку обещаний X с мангустом». Недостатком, когда вы разделяете вещи на отдельные модули, является то, что сложно сказать «хорошо, эта версия mongoose-promises работает только с mongoose 3.8, эта работает с mongoose> = 4.1», и мангусту трудно избежать нарушения всеобъемлющей оболочки обещаний. .

Это определенно достойная альтернатива. Тем не менее, я хотел бы сдержать обещания внутри компании, потому что, нравится вам это или нет, пользователи будут использовать mongoose именно так, поэтому мы могли бы иметь для него надежное тестовое покрытие,

Зачем вам нужно/нужно тестовое покрытие для этого? Нет смысла тестировать сами промисы в вашем коде — в библиотеках уже есть тесты — это все равно, что тестировать модуль http , когда вы его используете.

и мангусту трудно избежать нарушения всеобъемлющей оболочки обещаний.

Bluebird делает что-то очень простое — находит прототипы, а затем добавляет к ним методы с суффиксом Async — это действительно просто и хорошо работает на практике — это один лайнер с большинством библиотек, включая Mongoose, и он не ломается даже один раз для меня в прошлом году.

Я не уверен, почему вы хотите поддерживать много кода сшивки, который потенциально подвержен ошибкам, необходимость вручную поддерживать два API с их крайними случаями звучит как много работы, и вы можете сломать что-то по ходу дела - вы можете «одолжить» код bluebird promisifyAll и адаптировать его для работы с другими библиотеками обещаний (в конце концов, это открытый исходный код), но я, конечно, не стал бы делать это вручную.

«хорошо, эта версия мангуста-промисов работает только с мангустом 3.8, эта работает с мангустом> = 4.1», и мангусту трудно избежать нарушения всеобъемлющей оболочки обещаний.

Хорошо, не могли бы вы привести мне пример кардинального изменения, которое должно было бы произойти, если бы обещание было автоматическим?

1) Я хотел бы протестировать вещи так, как их используют пользователи.

2) Я хотел бы быть ленивым и избегать этого, но, насколько я понимаю, большинство других библиотек промисов не имеют эквивалента promisifyAll. Я предполагаю, что именно поэтому «поддержка функции Xpromise Y» является самым популярным запросом функции мангуста. Кроме того, мы не собираемся переписывать промисификацию Bluebird, просто заставим функции мангуста возвращать промис изначально.

3) Зависит от реализации обещания и от того, как вы его используете :)

1) Я хотел бы протестировать вещи так, как их используют пользователи.

Что вы подразумеваете под тестированием того, как пользователи их используют? Можете ли вы показать мне аналогию для обратных вызовов?

2) Я хотел бы быть ленивым и избегать этого, но, насколько я понимаю, большинство других библиотек промисов не имеют эквивалента promisifyAll. Я предполагаю, что именно поэтому «поддержка функции Xpromise Y» является самым популярным запросом функции мангуста. Кроме того, мы не собираемся переписывать промисификацию Bluebird, просто заставим функции мангуста возвращать промис изначально.

Вам не нужно переписывать, вы можете взять это - это не общее, поскольку общая реализация будет медленнее.

Также не лень не реализовать вручную широкодоступную фичу. NodeJS ленив, потому что не ставит экспресс в ядро? TC39 ленив, потому что не ставит подчеркивание в ядре? Придерживаясь соглашения (обратных вызовов), вы даете пользователям возможность использовать любой примитив параллелизма, который они хотят.

3) Зависит от реализации обещания и от того, как вы его используете :)

Что ж, промисификация bluebird, Q или When — они различаются по реализации, но все они делают одно и то же — так что просто выберите то, что вам нравится. Мне просто интересно, как он сломается.

В этом обсуждении мне не хватает одной вещи:

Если mongoose возвращает стандартное обещание (по стандарту это означает нативную реализацию ES6), разве оно не должно быть совместимо с любой библиотекой Promise, совместимой с ES6? Я могу сделать Promise.all([model.query().exec(), ...]) просто отлично, а также синюю птицу, q, когда это эквивалентно.

Итак, почему бы не вернуть обратные вызовы и стандартные обещания (как это делается сейчас, но "избавиться" от mpromise) и позволить пользователю использовать его любимую библиотеку обещаний? Или я что-то здесь упускаю?

@albertorestifo хорошо, нативные обещания в данный момент работают медленно, и потребуется время, возможно, годы, прежде чем они достигнут паритета с пользовательскими библиотеками - так что в основном это.

@benjamingr , ты сделал несколько хороших замечаний. Основная цель обещаний мангуста — позволить вам использовать yield с асинхронными операциями мангуста без какой-либо другой библиотеки, поэтому мы держим обещания в обозримом будущем. ИМО, это то, что действительно должно быть частью ядра мангуста в будущем.

Имеют ли Q или When возможность обещания?

Имеют ли Q или When возможность обещания?

Да, практически каждая широко распространенная библиотека обещаний, которую я знаю, предлагает какие-то обещания:

Вот когда: https://github.com/cujojs/when/blob/master/docs/api.md#nodeliftall
Вот вопрос: https://github.com/kriskowal/q/wiki/API-Reference#qnfbindnodefunc -args

В нативных промисах его еще нет, но над этим ведется работа — как только появится быстрый путь для создания промисов (то есть — не конструктор промисов), NodeJS, скорее всего, будет поддерживать его в ядре для нативных промисов (поскольку он может « это не должно быть сделано _быстро_ в пространстве пользователя).

Основная цель обещаний мангуста - позволить вам использовать yield с асинхронными операциями мангуста без какой-либо другой библиотеки.

Вам нужна библиотека, чтобы в любом случае использовать yield осмысленно с промисами. Если вы можете сами написать 9 LoC, которые перекачивают генератор как асинхронную функцию, вы определенно можете написать promisify — и если вы похожи на большинство пользователей, вы все равно используете для этого библиотеку.

Я определенно вижу желание/необходимость разрешать промисы в Mongoose, это путь вперед и то, как язык делает параллелизм сейчас, но я честно думаю, что делать это вручную метод за методом будет болезненно. Может быть полезно просто продемонстрировать, как это делается с помощью библиотек, в разделе документации «использование с промисами» или «использование с генераторами».

Дело в том, что мы уже сделали это метод за методом, нам просто нужно изменить внутреннюю обёртку промиса. В любом случае, мы не можем полностью удалить промисы из ядра до версии 5.0. Я согласен с идеей отказаться от этого, @benjamingr действительно приводит несколько хороших аргументов, которые мне придется внимательно рассмотреть, но я думаю, что следующим шагом в любом случае будет # 2688.

У вас, очевидно, больше опыта работы с Mongoose и, что более важно, с его пользователями, поэтому я понимаю этот выбор. Большое спасибо, что выслушали меня.

Я набрал «его», но мой iPhone чувствовал, что он должен автоматически исправить его на «это», а GitHub посчитал, что редактирование комментариев не является интересным вариантом использования. Извините за двойной спам в комментариях :)

Вы можете редактировать комментарии на веб-сайте, нажав на карандаш в правом верхнем углу вашего комментария.

Я всегда открыт для хороших душевных дебатов, особенно тех, которые учат меня чему-то новому :beers: Я могу связаться с вами позже, чтобы обсудить больше :)

Похоже, будущее принадлежит родным обещаниям. Mongoose — это отраслевой стандарт для mongo ops, он также может полагаться на стандартные обещания.

Стандартные промисы неизбежно созреют и станут более распространенными, чем любой фреймворк. Скромный +1 за их использование.

@iliakan , возможно, в будущем. Я бы не ожидал, что нативные промисы станут «стандартом» самое раннее до середины 2016 года, различные фрагментированные библиотеки промисов слишком глубоко укоренились и имеют слишком много тонких особенностей. В любом случае, мангуст не может переключиться на «родной по умолчанию» без значительных изменений назад.

@vkarpov15 конечно понимаю.

Что может быть полезно тем временем - простая страница, которая описывает основные несовместимости между mpromise и нативными промисами. По крайней мере, то, что вы не должны пробовать с mpromise ;)

Я правильно понимаю, что сейчас нет catch , и это все ограничения?

Понятия не имею, на самом деле не копался в API ES6. mpromise реализует Promises/A+ и ничего больше, что означает отсутствие .catch(), длинных трассировок стека и т.д. и т.п. По сути, все, что не .then() , выходит за рамки реализации mpromise.

Вообще говоря, что-то, что реализует Promises/A+, также реализует обещания ES6 с точки зрения высокого уровня, но обратное неверно. Промисы/A+ очень специфичны в отношении деталей низкоуровневой реализации, например, bluebird не полностью подчиняется Promises/A+, и я не уверен в других распространенных библиотеках промисов, но я уверен, что они не подчиняются спецификации в свои уникальные способы. Вот что сделает это особенно сложным.

Вы имеете в виду, теперь можно использовать bluebird и нативные промисы?

Yup require('mongoose').Promise = global.Promise заставит мангуста использовать нативные промисы. Вы должны иметь возможность использовать любой конструктор промисов ES6, но сейчас мы тестируем только нативные, bluebird и Q.

@vkarpov15 Это здорово! Большое спасибо!

@vkarpov15 Большое спасибо! Прекрасная работа!

Определенно да. Это действительно круто! :)

@vkarpov15 Это действительно мило

Была ли эта страница полезной?
0 / 5 - 0 рейтинги