2015-11-02 2 views
13

Я рассматриваю функции обработки, которые возвращают обещания с функциями Ramda, отличными от pipeP. Я пытаюсь сравнить функции (один из которых возвращает обещание) с равными, как это:Обработка асинхронного программирования с помощью Ramda

getSectionFromDb :: obj -> promise 
getSectionFromData :: obj -> number 

R.equals(
    getSectionFromDb, 
    getSectionFromData 
) 

Есть два фактора при игре здесь. Сначала R.equals не будет оценивать функции, но большая проблема заключается в том, что я сравниваю обещание с числом.

Есть ли функциональный способ делать такие вещи (я знаю, что функции не являются ссылочными прозрачными, но должен быть способ борьбы с io)? Есть ли способ Рамды сделать это?

Спасибо.

+2

Звучит так, будто вы хотите «поднять» функцию 'equals' - сначала в монаде обещаний, а затем в аппликативной функции; К сожалению, Рамда может только подбирать списки. – Bergi

+0

Значит, вам нужна функция '??? :: (obj -> Promise ) -> (obj -> number) -> (obj -> Promise ) '? – Bergi

+0

@ Bergi: документация Рамды здесь не совсем подходит, но «поднять» ** [работает на произвольных «аппликативных функциях»] (https://github.com/ramda/ramda/blob/master/test/liftN .js # L42-L45) **. –

ответ

3

Вы можете использовать Promise.resolve для «обертывания» значения в обещании.

getSectionFromDataPromise :: obj -> promise 
getSectionFromDataPromise = R.pipe(getSectionFromData , (val) => Promise.resolve(val)) 

Таким образом, вы можете повысить (поднять) любую функцию, которая возвращает нормальное значение, которое возвращает обещание.

Подъем является важной концепцией в FP. Вы можете просмотреть Array.map как функцию, которая поднимает функцию, которая преобразует значение в функцию, которая преобразует массив значений.

Вы можете использовать Promise.all, чтобы написать функцию, которая сравнивает обещания и (например) выдает ошибку, если они не равны.

function promiseEquals (f1, f2) { 
    return Promise.all([f1(), f2()]).then(function(vals) { 
    if(!R.equals(vals[0], vals[1])) {throw "The values aren't equal"} 
    return vals[0] 
    }) 
} 

Наконец вы можете объединить два:

promiseEquals(getSectionFromDataPromise, getSectionFromDb) 
    .then(function(val){ 
    console.log(val) 
    }) 
    .catch(function(val){console.log("Error "+val)}) 
+0

Не (val) => Promise.resolve (val) просто многословный способ сказать Promise.resolve? – arcseldon

+0

в идеале да, в JS нет. Функция разрешения не связана с объектом Promise. –

+1

@arcseldon Вы можете сделать 'getSectionFromDataPromise = R.pipe (getSectionFromData, Promise.resolve.bind (Promise));' –

9

Я знаю, вопрос старый. Но у ramda есть некоторые классные функции для создания функций Promise-return: pipeP и composeP.

Также обратите внимание на регулярные compose (pipe) и его реализация Клейсли composeK (pipeK). Они позволяют работать с алгебраическими структурами, такими как Future или Task, которые выглядят так же, как Promise, но лениво оцениваются.

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