Jshint: переопределение Обещания (W079)

Созданный на 30 июн. 2014  ·  48Комментарии  ·  Источник: jshint/jshint

Я только что перешел с 2.4.4 на 2.5.1
Но теперь все мои требования испорчены, потому что:

var Promise = require('bluebird')
Предупредит о:
Redefinition of Promise (W079)

Я могу это как-то исправить? Я использую bluebird повсюду.

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

var Promise = Promise || require('bluebird')

Это ужасно, никогда так не делай

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

Хм, это потому, что Promise теперь является встроенным глобальным. Это хороший момент, который нам нужно как-то исправить. Маркировка как P1.

Кроме того, я не вижу, как я могу отключить Promise как встроенный глобальный. Я пытался установить browser: false , но он по-прежнему считается глобальным.

+1 Я использую browser: false и node: true . Вы могли бы подумать, что это сработает, если только Node не планирует добавить Promise при обновлении V8.

@gabegorelick Обещания уже находятся в нестабильном узле, поэтому я почти уверен, что они будут в узле V0.12, если они когда-нибудь его выпустят...
Я думаю, что нам, вероятно, нужен более явный флаг, чем node или browser , чтобы разрешить это переопределение, чтобы разрешить период адаптации к нативным промисам.

наткнись на это. получая те же ошибки.

Вы бы написали это?

var Array = require("my-array-implementation");

...или перекрыть любой другой встроенный объект?

Отличный момент. Не могли бы вы предложить использовать какую-то альтернативу, например, BluebirdPromise ? Я открыт для этого, просто понравилась читабельность, и я определяю. не хочу ничего прокладывать.

Конечно, или BPromise, или что-то еще, что-то, что не будет конфликтовать с другим кодом, который может ожидать, что Promise будет тем, чем он является. Факт: сообщество хотело, чтобы Promise был встроен в язык, что и произошло. Побочным эффектом является то, что слово «Обещание» больше не является бесплатным для всех.

@rwaldron Я действительно согласен с тобой. Я просто переименую свои ссылки.

Хороший звонок @rwaldron , я согласен.

Здорово! Это очень прогрессивное решение :D

Вместо переименования моих ссылок я нашел другое решение:
Я только что добавил следующее в свой файл .jshintrc

"globals"      : {
    "Promise"   : true
}

Работает отлично !
РЕДАКТИРОВАТЬ: чтобы было ясно, я не думаю, что это очень хорошее решение, сейчас это самое простое для меня. Использование альтернативной ссылки, такой как BPromise , кажется мне лучшим решением.
Я бы не стал использовать Bluebird в качестве ссылки, как здесь: https://github.com/krakenjs/kraken-js/commit/701f4c34753e53cec24da84ac9bf658243e83e6c . Обещание вне зависимости от реализации.

@rwaldron Я бы не согласился с тем, что the community wanted Promise baked into the language является причиной сделать Promise глобальным именем, потому что сейчас язык != среда Node.js != среда браузера. jshint не должно быть таким ограничительным в этом случае, я бы также сказал, что это обратно несовместимое изменение, которое попало в минорное обновление версии, которое начало влиять на все наши (и, возможно, другие) сборки. Я не думаю, что вы станете спорить с тем, что многие разработчики используют bluebird и назначают его Promise , и я не думаю, что мы увидим нативные Promise в Node.js достаточно скоро, чтобы объявить Promise глобальным повсюду. Даже когда у нас везде будет Promise , будет сложно переключиться с bluebird или любой другой библиотеки, которую используют люди, потому что они также используют дополнительные API, предоставляемые этими библиотеками. Обходной путь с globals: { ... } также является плохой идеей, потому что вы вводите горячую точку, и если разработчики забудут сделать var Promise = ... , jshint не будет жаловаться, но ваш код произойдет сбой во время выполнения. Мое предложение было бы либо убедиться, что Promise не является глобальным по умолчанию, когда node: true ИЛИ полностью отменить изменение и позволить людям решать, пока мы не увидим, что Promise включено по умолчанию (w/ o дополнительные флаги или магия и т.д.) в Node.js и браузере.

Promise уже является глобальным в V8/node, если вы передаете --harmony-promises или --harmony .

В V8 3.28.71.2 коллекции Promise, Symbol и гармонии (Map/Set/WeakMap/WeakSet) включены по умолчанию (скоро появятся массивы гармоний и несколько других функций), так что на самом деле это всего лишь вопрос времени, когда они включены по умолчанию, если только joyent/strongloop явно не удалит эти глобальные переменные во время начальной загрузки, что кажется маловероятным.

Promise является частью экосистемы, но иметь возможность отключать глобальные переменные es6 в конфигурации, IMO, имеет смысл. (если вы хотите узнать, как появятся другие функции, http://www.chromestatus.com/features#es6 — хороший индикатор того, когда они появятся в V8 и когда они будут включены по умолчанию).

Что бы это ни стоило, Mozilla даже не скрывает функции гармонии за предпочтениями, и ряд этих функций включен по умолчанию в Chrome — так что это действительно среда browser . Что касается узла, как сказано выше, это действительно вопрос времени.

@caitp Не в узле v0.10.x и v0.12.x еще не выпущены (и, вероятно, не будут выпущены в течение следующих N месяцев), и даже когда они появятся в этом мире, я сомневаюсь, что люди собираются немедленно переключитесь, и я еще больше сомневаюсь, что люди будут работать с --harmony-promises в продакшене. Я согласен, однако, что в конфигурации должна быть какая-то опция es6. Это была бы победа для всех.

есть опция es6, но глобальные переменные Promise, Symbol, Reflect, Map, Set, WeakMap и WeakSet не предопределены на основе наличия этого флага.

Может быть, они должны быть, вероятно, это довольно простой CL для сборки

@xaka Я добавил все новые глобальные имена API в список идентификаторов Ecma и не буду их удалять. Начиная с версии 2.5.4 вы можете сделать это:

/* global -Promise */
var Promise = require("promise");

Или в predef в .jshintrc:

{
  "undef": true,
  "unused": true,
  "predef": [ "-Promise" ]
}

Есть ли причина, по которой следующее не будет работать на уровне модуля?

var Promise = global.Promise  || require("promise");

или это на глобальном

var Promise = Promise  || require("promise");

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

Интересно, почему предупреждение также выдается для области видимости блока:

const Promise = require('bluebird');  // same for `let`

В этом случае глобальная переменная останется нетронутой.

Если вы можете использовать функции ES6 (узел 0.11+) и #2090 исправлено, то переименование переменной больше не нужно.

В этом случае глобальная переменная останется нетронутой.

Верно, и это должно быть зарегистрировано как другая проблема — что вы и сделали, спасибо!

Но...

Если вы можете использовать функции ES6 (узел 0.11+) и #2090 исправлено, то переименование переменной больше не нужно.

let и const в версии 8 (как показано в узле 0.11.x) являются реализацией прототипа, которая больше не является правильной (например, устаревшей на несколько лет) и, следовательно, _не_ является функцией ES6, поэтому вам _на самом деле_ не следует их использовать, потому что они не соответствуют семантике спецификации.

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

На самом деле, пожалуйста, не используйте их (ни в узле, ни в веб-приложениях) --- иначе мы никогда не сможем реализовать "правильное" поведение ;_; и это было бы грустно. Если вы видите устаревшее поведение let/const в дикой природе, сообщите соответствующим людям, чтобы они удалили его.

@caitp +9001

Кто-нибудь может сослаться на информацию о том, что изменилось в const и let ?
Мне не удалось найти никакой информации об этом, и я не вижу причин не использовать его в Node.

@fluidsonic похоже, что версия v8, работающая в узле 0.10.35, имеет семантику TDZ , но let и const по-прежнему намеренно (и неправильно) ограничены кодом строгого режима.

Всем привет,

JSHint 2.8.1 ( выпущенный сегодня ) включает новую опцию с именем futurehostile , которую мы разработали как более понятную альтернативу predef: ['-Promise'] . Надеюсь, это поможет!

^ _2.6.1_

Не знаю, как это понятнее, но тем не менее... ;)​

Даже с Promise в версии 8/io.js, смертельно медленным и _непохожим на _ Array , Promise был специально разработан для обеспечения альтернативных и интероперабельных реализаций.

Promise = require('bluebird');

должно быть предупреждение

var Promise = require('bluebird');

не должно быть, имхо. Я пошел глобальным путем, банкомат.

@domenic - хотелось бы, чтобы вы здесь написали. Является ли переопределение window.Promise в Интернете или global.Promise на узле/iojs в локальной области перспективным?

Пример:

var Promise = require('bluebird');

Является ли переопределение window.Promise в Интернете или global.Promise на узле/iojs в локальной области перспективным?

Это самопротиворечиво.

Нет, это будущее враждебно.

@domenic - Спасибо!

@rwaldron -

Это самопротиворечиво.

Извините за путаницу. Я обновил свой вопрос для ясности. Я имел в виду, что «это переопределение встроенной функции Promise в локальной области видимости».

Примеры, предоставленные @petkaantonov в bluebird , переопределяют встроенную функцию Promise , что заставило меня задаться вопросом, действительно ли (в случае промисов - в соответствии с комментарием @sam-github) это было действительно принятой практикой.

Похоже, ответ "нет".

https://github.com/jshint/jshint/issues/1747#issuecomment-94024023

@domenic почему будущее враждебное? Промисы были специально разработаны спецификацией для поддержки альтернативных сосуществующих реализаций... почему бы не назвать реализацию промиса, используемую в конкретном модуле узла, Promise , а не, скажем, Bluebird или MyPromise ?

Это как-то запутает оптимизатор v8? Я бы так не думал.

Или это потому, что вы надеетесь, что все другие реализации промисов умрут и останется только одна доставка в среде выполнения js?

По той же причине в будущем враждебно перезаписывать Object , Map или window .

Понятия не имею. var Promise = Promise || require('bluebird') кажется перспективным, а не враждебным будущему. Object всегда существовал, Promise почти не существует.

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

По той же причине в будущем враждебно перезаписывать объект, карту или окно.

Ага, именно так, как я уже говорил.

Ах, ну, это просто ходит по кругу, но любая серьезная попытка убедить мир в том, что весь существующий код, в котором есть var Promise , внезапно стал неправильным в последнее время (даже в средах, которые _не имеют реализации Promise_, например, довольно весь код узлов в производстве), потребуется немного больше работы.

Проведение аналогий между встроенными типами Promise и js, которые существовали десятилетиями, требует немного большей поддержки, чем просто утверждение, что они аналогичны.

(даже в средах, в которых нет реализации Promise, как и почти весь код узла в производстве)

У JSHint нет возможности узнать, в какой среде выполнения будет выполняться анализируемый им код. JSHint не собирается ломать чей-либо производственный код. Если вы хотите обойти привязки Identifer встроенных объектов, просто сделайте это и скажите JSHint, чтобы он заткнулся.

просто сделайте это и скажите JSHint, чтобы он заткнулся

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

var Promise = Promise || require('bluebird')

Это ужасно, никогда так не делай

Как эта проблема должна быть исправлена ​​в конце?

я пробовал

futurehostile : true,

Но все же есть это предупреждение:
image

С другой точки:

predef   : ['angular','-Promise']

работает, но, как я понимаю, я должен придерживаться первого решения.

Есть предположения?

У меня похожая проблема:
У меня есть файл, который я использую как в браузере, так и в узле;
Когда я работаю в браузере, я полагаюсь на то, что функция является глобальной функцией (это объект, который содержит кучу пользовательских сопоставителей для jasmine), но когда он находится в узле, я экспортирую его через module.exports.

"use strict";
var module = module || {
    exports : {}
};

function Matchers(){ 
    // code...
}
// code...

module.exports = Matchers;

Jshint выдает ошибку:

  line 3  col 5  Redefinition of 'module'.

два вопроса:

  1. Если то, что я делаю, в порядке, это ошибка с jshint?
  2. Если я не должен этого делать, что мне делать?

@andrew-luhring рядом с пустым блоком в конструкторе, это пройдет:

"use strict";
var module;
if (!module) {
    module = {
        exports: {}
    };
}

function Matchers() {
    // put something here
}

module.exports = Matchers;

какая разница? на самом деле нет никакой конкретной разницы с тем, что вы написали, это просто более длинный и, возможно, понятный способ сделать то же самое (я бы также использовал вашу версию, попробуйте JSHint ;-))

Ваше здоровье

Я, наверное, что-то упускаю, но есть ли способ подавить эту ошибку? Я использую esnext: true , который генерирует ошибку, и пробовал такие разные варианты, чтобы переопределить конкретное поведение Promise, например

  "globals": {
    "Promise": false // or true
  },
  "-Promise": false,
  "predef": [ "-Promise" ]

но ни один из них, кажется, не переопределяет ошибку.

Ошибка возникает только с let Promise = и const Promise= . Нет ошибки с var Promise=

Обновление : после некоторого futzing я получил его для работы с
"globals": { "Promise": null }

Привет @joegoldbeck. Хотя я рад, что вы нашли обходной путь, который решил вашу
Проблема в том, что это не официально поддерживаемое использование конфигурации globals .
Поскольку мы не документируем и не тестируем его, он может не работать в будущем выпуске
JSHинт. Я только что проверил, что следующая конфигурация подавляет предупреждение
вы сообщили о привязках let и const :

{
  "esversion": 6,
  "predef": ["-Promise"]
}

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

Привет , @jugglinmike, спасибо за ответ! Я бы предпочел использовать поддерживаемую конфигурацию. Тот, который вы предлагаете, у меня почему-то не работает. Я удалил свой .jshintrc, чтобы он содержал только эти строки, и я все еще получаю предупреждение W079. Я использую JSHint v2.9.4 в WebStorm.

Я хотел бы отметить, что по сей день, по состоянию на апрель 2017 года, документы Bluebird по-прежнему рекомендуют это использование в Node:

var Promise = require("bluebird");

и в каждой отдельной части документации используются имена вроде Promise.promisifyAll (не Bluebird.promisifyAll ) для описания методов, доступных в Bluebird, но не в родном Promise.

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

См.: http://bluebirdjs.com/docs/getting-started.html .

Кроме того, кажется, что Bluebird не согласен с тем, что переопределение Promise является плохой идеей - см. проблему petkaantonov/bluebird#715 - так что кажется, что следующие примеры Bluebird приведут к разрыву кода с ESLint. Похоже, здесь нет единого мнения.

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