2016-05-05 2 views
2

я вижу следующий подход часто при работе на некоторых проектах, которые используют Node.js и Bluebird.js:Устранение ненужных функций-оберток в обработчиках `. Then`?

function someAsyncOp(arg) { 
    return somethingAsync(arg).then(function (results) { 
     return somethingElseAsync(results); 
    }); 
} 

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

function someAsyncOp(arg) { 
    return somethingAsync(arg).then(somethingElseAsync); 
} 

Когда я предлагаю его другим, они, как правило, как это и переключиться на него.

Существует, однако, важное предостережение: если вы вызываете что-то вроде object.function, а функция опирается на this (как console.log делает), то this потеряет свою силу. Вы должны сделать object.function.bind(object):

return somethingAsync(arg).then(somethingElseAsync).catch(console.log.bind(console)); 

Это, кажется, потенциально нежелательным, и .bind вызов чувствует себя немного неловко. Вы не ошибетесь в подходах let's-always-do-the-close.

Возможно, я не могу найти что-либо по этому поводу в google, в ESLint ничего не говорится о ненужных функциях-оболочках. Я пытаюсь узнать больше об этом, так что я здесь. Наверное, это случай, когда я не знаю, чего не знаю. Есть ли это имя? (Бесполезное использование закрытий?) Любые другие мысли или мудрости? Спасибо.

Редактировать: кто-то собирается прокомментировать, что someAsyncOp также является избыточным, да, это так, давайте притворимся, что он делает что-то полезное.

ответ

2

Обсуждение здесь довольно простое. Если ваша функция в порядке, вызывается непосредственно системой обещаний, с точными аргументами и значением this, которое будет на месте, когда его вызываемый непосредственно системой обещаний и его возвращаемое значение именно то, что вы хотите в цепочке обещаний, затем всеми значит, просто указать ссылку на функцию непосредственно как .then() обработчика:

somethingAsync(arg).then(somethingElseAsync) 

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

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

Все функции обратного вызова имеют одинаковую проблему с передачей obj.method в качестве обратного вызова. Если ваш .method ожидает, что значение будет obj, вам, вероятно, придется что-то сделать, чтобы убедиться, что значение this установлено соответствующим образом перед выполнением вашей функции. Обратные вызовы в обработчиках .then() не отличаются от обратных вызовов для любой другой функции Javascript/node.js, такой как setTimeout() или fs.readFile() или другой другой функции, которая выполняет обратный вызов в качестве аргумента. Таким образом, ни один из вопросов, которые вы упомянули, не уникален для обещаний.Так получилось, что обещания живут обратными вызовами, поэтому, если вы пытаетесь сделать вызовы методов через обратный вызов, вы столкнетесь с проблемой, когда значение объекта будет передано соответствующим образом методу.

FYI, можно кодировать методы так, чтобы они были постоянно привязаны к их собственному объекту и могут быть переданы как obj.method, но это может быть использовано только в реализации вашего метода и имеет некоторые другие компромиссы. В целом, опытные разработчики Javascript отлично справляются с использованием obj.method.bind(obj) в качестве ссылки на пропуск. Увидев код .bind(), код также указывает, что вы знаете, что вам нужно надлежащее значение obj внутри метода и что вы сделали это для этого.

В некоторых из ваших полужирных вопросов или комментариев:

Есть ли имя для этого?

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

Любые другие мысли или мудрости?

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

Вы не ошибетесь в подходе let's-always-do-the-close.

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

Смежные вопросы