Вопрос: Промисифицировать синхронные операции для цепочки промисов?

Есть ли смысл обещать синхронные операции, чтобы по замыслу их можно было объединить в обратные вызовы onSuccess или onError?

Eg:

function loadSettings(path) {
    if (fs.existsSync(path)) {
        return Q(fsJson.loadSync(path));
    }
    return new Q.defer().reject('No local settings!');
}

doingSomethingFirst()
    .then(loadSettings, obtainSettings)
    .then(doSomethingWithSettings)
    .done()

Что лучше?


person asking    schedule 11.05.2015    source источник


Ответы (2)


Нет, кроме того, создается ложное впечатление, что эти методы являются асинхронными, поэтому вы или другие разработчики можете вызвать их и ожидать, что метод не подрывает всю модель параллелизма io.js/node.js, выполняя синхронный ввод-вывод.

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

person Benjamin Gruenbaum    schedule 11.05.2015
comment
@gruenbaum Спасибо за ответ. Что касается состояния гонки, как повысить безопасность синхронной загрузки? Попробуйте/перехватите вызов fsJson.loadSync(path), затем проверьте, есть ли файл, прежде чем вернуться? - person asking; 11.05.2015
comment
Да, просить прощения, а не разрешения. - person Benjamin Gruenbaum; 11.05.2015

На самом деле эта конкретная цепочка будет работать точно так же, даже если вы напишете loadSettings так:

function loadSettings(path) {
    if (fs.existsSync(path)) {
        return fsJson.loadSync(path);
    }
    throw 'No local settings!';
}

Обратите внимание, что это ужасная практика - отклонять строки или выбрасывать строки, поэтому в идеале вместо этого вы хотите new Error('No local settings!'). Я имею в виду, просто представьте, если бы эта ошибка действительно произошла, и это была бы просто строка - вы бы понятия не имели, как и где на самом деле произошла ошибка.

person Esailija    schedule 11.05.2015
comment
Ну, технически в Bluebird вы бы так и поступили, не так ли? (Тем не менее, это ужасная идея бросать строки, и есть проблема состояния гонки, и подрыв io/node и т. д.). - person Benjamin Gruenbaum; 11.05.2015
comment
@BenjaminGruenbaum нет iirc, он был удален, во многих случаях трассировка на самом деле была бесполезна - person Esailija; 11.05.2015
comment
Действительно? Итак, если вы выдаете строку с длинными трассировками стека, bluebird не будет генерировать длинную трассировку стека, как раньше? Это позор, поскольку иногда вы вынуждены использовать внешние библиотеки, которые возвращают промисы или код, который их использует, а иногда они выдают строки, потому что ненавидят разработчиков. Делать .nodeify и .promisify кажется глупым :D - person Benjamin Gruenbaum; 11.05.2015
comment
Почему это было удалено? Перф? - person Benjamin Gruenbaum; 11.05.2015
comment
внутренняя сложность для чего-то, что на самом деле не нужно - person Esailija; 11.05.2015
comment
Ну, в теории я думаю, что это полезная функция, но на практике я этого не замечал до сих пор - так что вот что :) - person Benjamin Gruenbaum; 11.05.2015