2017-10-05 2 views
1

Comment puis-je utiliser R.cond avec des promesses?Conditionnel avec la promesse dans Ramda

Quelque chose comme ça ..

const fetchBin = (url) => fetch(`https://httpbin.org${url}`).then((response) => { 
 
    var contentType = response.headers.get("content-type"); 
 
    if(contentType && contentType.includes("application/json")) { 
 
     return response.json(); 
 
    } 
 
    throw new TypeError("Oops, we haven't got JSON!"); 
 
}) 
 

 
const testStatus = (status) => fetchBin(`/status/${status}`); 
 

 
const isOk = R.propEq('statusCode', 200); 
 
const testCond = R.cond([ 
 
    [ R.pipeP(testStatus, isOk), (resp) => console.log('The resp is ', resp) ], 
 
    [ R.T, (code) => console.log('The resp is NOT ok', code) ] 
 
]) 
 

 
testCond(404) 
 
// R.pipeP(testStatus, isOk)(404)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>

+0

Je pense que vous devriez avoir une partie 'testCond' dans un' then' de 'testStatus', car selon les docs de Ramda, le prédicat est censé être une fonction pure dans' cond'. –

Répondre

2

Je pense que c'est ce que vous recherchez, en composant avec testStatus vous devriez être en mesure d'obtenir l'objet response et faire le branchement conditionnel .

const fetchBin = (url) => fetch(`https://httpbin.org${url}`).then((response) => { 
 
    var contentType = response.headers.get("content-type"); 
 
    if(contentType && contentType.includes("application/json")) { 
 
     return response.json(); 
 
    } 
 
    throw new TypeError("Oops, we haven't got JSON!"); 
 
}) 
 

 
const testStatus = (status) => fetchBin(`/status/${status}`); 
 

 
const isOk = R.propEq('statusCode', 200); 
 
const testCond = R.pipeP(testStatus, R.cond([ 
 
    [isOk, resp => console.log('The resp is OK :' + resp.statusCode)], 
 
    [R.T, resp => console.log('The resp is NOT OK :' + resp.statusCode)] 
 
])); 
 

 
testCond(404) 
 
// R.pipeP(testStatus, isOk)(404)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.24.1/ramda.min.js"></script>

+0

Bonjour @MinusFour, j'ai essayé votre suggestion mais je n'ai pas travaillé. 'R.pipeP (testStatus,/* Si la promesse n'est pas résolue (attraper dans ce cas) la condition n'est pas exécutée * /)' Vous pouvez vérifier [ici] (https://runkit.com/ridermansb/ramda-promises) – ridermansb

+1

Cela va être un peu un problème si vous dépendez de la clause catch, vous devrez remplir la promesse même si elle rejette. J'avais l'impression que même pour 400 codes d'état, vous renvoyiez une réponse JSON avec une propriété de code d'état 400. – MinusFour

2

une nouvelle perspective

il est bon de nous rappeler que nous devons être ceux de flexion nos langages de programmation, et non l'inverse

Il me semble que vous êtes en train de battre le mauvais chemin. fetchBin est un homme de paille du gars que nous recherchons vraiment. Nous avons besoin d'une fonction qui prend une URL et renvoie la réponse JSON analysée; Appelons cet homme, fetchJSON

À partir de là, nous mettons en œuvre fetchBin utilisant fetchJSON - peu importe si la ressource retourne un statut 404 ou un statut 200 avec le mauvais type de contenu (voir l'exemple XML ci-dessous) - de toute façon , la promesse sera correctement routée vers le gestionnaire d'erreurs (console.error ci-dessous, ou alternativement .then(console.log).catch(console.error)) - le point ici, au cas où je ne suis pas clair, est que fetchBin ne devrait pas être concerné par des détails comme ce que le code de statut HTTP est ou quoi l'en-tête Content-Type de la réponse peut être - laissez-le simplement demander le JSON analysé, et arrêtez de vous inquiéter du reste

Ma raison de partager ceci est de vous aider à éviter de rester bloqué dans une façon de penser particulière. R.cond est une jolie forme de , si vous êtes parfaitement honnête - cela vous oblige à ajuster la sémantique de la fourche de votre programme en la mettant dans un tableau et en créant des branches conditionnelles qui ne seront peut-être jamais utilisées par votre programme; true la paresse n'est disponible que dans le JavaScript strictement évalué en utilisant if/else ou ?:; sans eux, vous êtes toujours faire un travail inutile

Une fois que nous nous UNBIND d'une forme rigide comme R.cond, les choses se emboîtent tout naturellement - Heck, nous ne finissons même par avoir besoin R.pipe ou R.pipeP, ou R du tout. ..

const fetchJSON = url => 
 
    fetch (url) 
 
    .then (responseOK) 
 
    .then (parseJSON) 
 

 
const responseOK = (response) => 
 
    { 
 
    if (response.status >= 200 && response.status < 300) 
 
     return response 
 
    else 
 
     throw Object.assign (Error (response.statusText), { response }) 
 
    } 
 

 
const parseJSON = response => 
 
    response.json() 
 
    
 
const fetchBin = (url) => 
 
    fetchJSON ('https://httpbin.org' + url) 
 

 
fetchBin ('/anything?a=b') .then (console.log, console.error) 
 
// all things good ! 
 
// => { args: {a: 'b'}, data: '' ... } 
 

 
fetchBin ('/status/404') .then (console.log, console.error) 
 
// non-200 status goes to error handler 
 
// => { Error: NOT FOUND ..., response } 
 

 
fetchBin ('/xml') .then (console.log, console.error) 
 
// bad JSON goes to error handler 
 
// => SyntaxError: Unexpected token < in JSON at position 0


Ok, donc on n'a pas besoin R là, mais cette réponse Cela ne veut pas dire que c'est une règle générale.Ramda est un excellent outil et peut vous apprendre beaucoup sur la programmation fonctionnelle. N'oubliez pas de prendre du recul parfois et d'évaluer si votre programme peut être exprimé d'une manière que vous voulez, plutôt que de vous soucier de ce que la langue (ou bibliothèque, ou function; R.cond) veut