AngularJS: Как избежать обработчиков анонимных обещаний
Недавно с моим клиентом мы решили следовать Руководству по стилю AngularJS Джона Папы*.
В настоящее время я прохожу текущую кодовую базу, чтобы удостовериться, что не осталось никакой анонимной функции. Однако я сталкиваюсь со случаем некоторых обработчиков обещаний, которые требуют параметров, установленных не ответом / отклонением обещания, а другой функцией или параметром. Я сделал несколько попыток передачи этих параметров в обратном вызове, но мне не удалось.
function testPromise() {
setPromiseAsPending();
var timestamp = new Date().toString();
firstModel.callPromise()
// option 1: use of anonymous functions. works, but not the aim.
// .then(
// function () {
// onPromiseResolved(timestamp);
// },
// function () {
// onPromiseRejected(timestamp);
// }
// )['finally'](setPromiseAsCompleted);
// option 2: naming functions in context. works, but less than ideal in our context.
.then(
function onPromiseResolved() {
secondModel.logPromiseResults('this promise has been resolved on ' + timestamp);
},
function onPromiseRejected() {
secondModel.logPromiseResults('this promise has been rejected on ' + timestamp);
}
)['finally'](setPromiseAsCompleted);
// option 3: passing functions as variables. not good: doesn't work, missing the parameter.
// .then(
// onPromiseResolved,
// onPromiseRejected
// )['finally'](setPromiseAsCompleted);
// option 4: calling functions with parameters. not good: both functions called.
// .then(
// onPromiseResolved(timestamp),
// onPromiseRejected(timestamp)
// )['finally'](setPromiseAsCompleted);
// option 5: how do i pass the parameter to only be used when the function is called?
Цель здесь - убедиться, что внутри функции не объявлено ни одной функции, чтобы каждая функция называлась и объявлялась на одном и том же уровне. Мы стремимся сократить длину функций, особенно чтобы сделать их более тестируемыми.
См. Фрагмент кода выше и дайте мне знать, если у вас есть предложение. Имейте в виду, что это не код, который мы используем, а минимальный прототип, имитирующий работу функции.
Смотрите код в github, если это вам поможет. Заранее спасибо за помощь.
* Не вступайте в религиозные дебаты по поводу руководства по стилю, это не предмет этого вопроса.
2 ответа
Вы могли бы использовать Function.prototype.bind
:
.then(
onPromiseResolved.bind(null, timestamp),
onPromiseRejected.bind(null, timestamp)
)['finally'](setPromiseAsCompleted);
Тогда ваша функция будет вызываться так же, как если бы вы это сделали onPromiseResolved(timestamp)
как в варианте 1.
Смотрите документы для получения дополнительной информации.
Вы не должны передавать параметр. Вам просто нужно объявить это в определении вашей функции.
Либо используйте "внешнее" объявление функции
function onPromiseResolved(timestamp) {
secondModel.logPromiseResults('this promise has been resolved with ' + timestamp);
}
function onPromiseRejected(err) {
secondModel.logPromiseResults('this promise has been rejected with ' + err);
}
….then(onPromiseResolved, onPromiseRejected)
или выражение именованной функции:
.then(function onPromiseResolved(timestamp) {
secondModel.logPromiseResults('this promise has been resolved with ' + timestamp);
}, function onPromiseRejected(err) {
secondModel.logPromiseResults('this promise has been rejected with ' + err);
})
Цель здесь - убедиться, что внутри функции не объявлено ни одной функции, чтобы каждая функция называлась и объявлялась на одном уровне.
Это довольно бесполезно. Иногда вам просто нужны замыкания (поскольку вы не хотите, чтобы все переменные были статическими глобальными переменными). Конечно, вы все равно можете их переместить и явно передать переменные замыкания в качестве аргументов:
function makeOnPromiseResolvedHandler(closurevars) {
return function onPromiseResolved(timestamp) {
secondModel.logPromiseResults('this promise has been resolved with ' + timestamp);
// use closurevars in here
};
}
….then(makeOnPromiseResolvedHandler(…), …)