2017-08-15 1 views
0

Lorsqu'une fonction attend un rappel comme param, je suppose que ce sens pour assurer une fonction liée comme celui-ciCallback ne peut pas être invoqué correctement, si le paramètre est une fonction liée

function invokeCb(cb){ 
    cb(); 
} 
function test(x){ 
    console.log(x) 
} 
const para="xyz"; 

invokeCb(test.bind(null,para)) //(1) 
invokeCb(()=>{test(para)}) //(2) 

Je ne vois pas quelque chose ne va pas avec (1). Cependant, quand il vient au monde réel, je rencontre un comportement inattendu

Voici un exemple, dans redux

store.subscribe(
    ()=>{(saveState.bind(null,store.getState()))()} 
) 

peut travailler pendant

store.subscribe(saveState.bind(null,store.getState())) 

ne peut pas correctement, à savoir le store.getState() semble jamais invoqué correctement

Si vous avez besoin de plus de contexte. Ici: https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage

Peut-être que j'ai manqué quelques différences subtiles entre les deux forme, quelqu'un peut le signaler?

Répondre

0

Les différences sont

  • l'heure à laquelle store.getState() est évalué
  • la valeur de retour (en utilisant des accolades sans return, vous supprimons)

let data = "abc"; 
function invokeCb(cb){ 
    data = "xyz"; 
    console.log(cb()); 
} 
function test(x){ 
    console.log(x); 
    return x.toUpperCase(); 
} 
invokeCb(test.bind(null, data)); // abc ABC 
invokeCb(()=>{ test(data); }); // xyz undefined 
+0

Je crois que vous connaissez la réponse, pourriez-vous donner un exemple concret aux démons trate la différence, je ne peux vraiment pas obtenir votre point – Guigui

+0

Vous êtes en quelque sorte correct, le problème est que 'stocker.getState() 'lire les données obsolètes – Guigui

+0

@Guigui J'ai ajouté un exemple (mais je ne l'ai pas essayé) – Bergi

0

Après quelques recherches, j'ai compris la vraie cause du bug!

Voici le code à démontrer:

function invokeCb(cb){ 
    cb(); 
} 
function test(x){ 
    console.log(x) 
} 

let counter=0; 
function getData(){ 
    return ({counter:counter++}) 
} 

const bindVersion=test.bind(null,getData()) 
const invokeVersion=()=>test(getData()) 

//first time 
invokeCb(bindVersion) //{counter:0} 
invokeCb(invokeVersion) //{counter:1} 

//second time 
invokeCb(test.bind(null,getData())) //{counter:0} 
invokeCb(()=>{test(getData())}) //{counter:2} 

//third time 
invokeCb(test.bind(null,getData())) //{counter:0} 
invokeCb(()=>{test(getData())}) //{counter:3} 

Explication:

  • Lorsque vous utilisez la version bind, le paramètre est fixe. c'est-à-dire une fois c'est bound il ne peut pas être changé.
  • D'une autre part, quand est fonction Invoke directement, le paramètre est dynamique, i.e.. il peut toujours obtenir les données mises à jour

Conclusion:

JAMAIS paramètre dynamique se lient à une fonction

Dans mon cas, le cas state est immutable dans redux, store.getState()return une nouvelle référence à chaque fois , en utilisant bind, il obtient toujours la première référence