2016-07-29 3 views
0

У меня есть следующий код в узле v6.3.0, запущенный на api, который запускает два отдельных обещания в зависимости от условности того, существует ли параметр в запросе POST.Сухие обещания в javascript

if (paramExists) { 
    // call database with this query 
    User.filter(/* do something with param */) 
     .then(function (user) { 
      Data.filter(/* same in both conditions */) 
       .then(function (data) { 
        // join data and user 
        res.send(joinedData); 
       }) // omit catch for clarity 
     }) // omit catch for clarity 
} else { 
    // call database with this query 
    User.filter(/* do something with header */) 
     .then(function (user) { 
      Data.filter(/* same in both conditions */) 
       .then(function (data) { 
        // join data and user 
        res.send(joinedData); 
       }) // omit catch for clarity 
     }) // omit catch for clarity 
} 

Я уверен, что есть способ DRY этот код так, что первое обещание в обоих случаях передает пользователю второе обещание, но я не могу понять, каким образом. Должен ли я использовать генератор, или есть способ сделать это с обещаниями, которые я не получаю?

+0

Вы считаете 'Promise.all'. В итоге это выглядит как «var p1 = User.filter (paramExists? Args1: args2), p2 = Data.filter (...); Promise.all ([p1, p2]), затем (функция (пользователь, данные) {...}); ' – numbers1311407

+0

Похоже, вы просите [условия в цепочках обещаний] (http://stackoverflow.com/ д/26599798/1048572)? – Bergi

ответ

2

Поскольку единственная часть, которая, кажется, отличается между двумя ветвями, что вы передаете User.filter(), вы можете поместить это значение в локальную переменную в условном выражении, а затем запустить одну версию кода с использованием переменной.

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

var arg; 
if (paramExists) { 
    arg = ...  // some logic 
} else { 
    arg = ...  // some different logic 
} 
// call database with this query 
User.filter(arg).then(function (user) { 
    return Data.filter(...); 
}).then(function (data) { 
    // join data and user 
    res.send(joinedData); 
}); // omit catch for clarity 

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

var arg = paramExists ? someLogic : someOtherLogic; 
// call database with this query 
User.filter(arg).then(function (user) { 
    return Data.filter(...); 
}).then(function (data) { 
    // join data and user 
    res.send(joinedData); 
}); // omit catch for clarity 

Если вам необходимо получить доступ как user и data для отправки ответа (немного сложно сказать в вашем псевдокоде), вы можете сохранить свою вложенность:

var arg = paramExists ? someLogic : someOtherLogic; 
// call database with this query 
User.filter(arg).then(function (user) { 
    return Data.filter(...).then(function(data) { 
     // join data and user 
     res.send(joinedData); 
    }); 
}); // omit catch for clarity 
+0

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

+0

@ numbers1311407 - Я добавил эту опцию обратно. Трудно сказать этот уровень детализации в псевдокоде несколько раз. Или они также могут делиться данными на одном уровне с одной из [этих схем] (http://stackoverflow.com/questions/28714298/how-to-chain-and-share-prior-results-with-promises/28714863 # 28714863). – jfriend00

+0

На самом деле да, второй вариант работает. Спасибо за это, научившись любить обещания. – alexi2

2

Вы можете сделать что-то следующее. Я предполагаю, что Data.filter также дает обещание.

if (paramExists) { 
    // call database with this query 
    User.filter(/* do something with param */) 
     .then(sameCondition); // omit catch for clarity 
} else { 
    // call database with this query 
    User.filter(/* do something with header */) 
     .then(sameCondition); // omit catch for clarity 
} 

function sameCondition(user) { 
    return Data.filter(/* same in both conditions */) 
    .then(function (data) { 
     // join data and user 
     res.send(joinedData); 
    }); // omit catch for clarity 
} 
+0

Вы можете пойти проще и просто передать разные параметры на первое обещание, основанное на условии, например. 'User.filter (paramExists? Args1: args2). Then (restOfBehavior);' – numbers1311407

+0

Выглядит достаточно просто, позвольте мне попробовать. – alexi2

1

ли что-то вроде этого ...

var task1 = paramExists ? 
    User.filter(/* do something with param */) : 
    User.filter(/* do something with header */) 

var doFilter = task1.then(function() { 
    return Data.filter(/* same in both conditions */) 
}) 

doFilter.then(function (joinedData) { 
    res.send(joinedData); 
}); 
Смежные вопросы