2016-07-24 1 views
0

J'ai une redux-forme qui passe des accessoires à mon action. La propriété this.props.userImages [0] est un fichier image provenant d'une entrée de fichier sur ce formulaire. Je prends alors cette image et rend XMLHttpRequest à Cloudinary qui génère une URL pour cette image. Une fois que je reçois les données d'url (xhr.responseText), je voudrais ensuite les fusionner avec mes autres accessoires afin que je puisse ensuite publier tous mes accessoires dans une API (toutes les informations de formulaire + URL d'image nouvellement créée).Comment gérer XMLHttpRequests dans une action redux?

Je sais que je dois attendre ma demande pour générer une URL à résoudre, mais avoir des problèmes avec l'obtenir juste avant de pouvoir la transmettre à mon autre fonction qui peut prendre cette information et la fusionner avec les accessoires avant de poster à mon API.

//.. 

function generateUrl(props) { 

    // Grabs image file from my form's file input and uploads 
    // to cloudinary service so that a URL can be generated 

    const cloudinaryURL = 'https://api.cloudinary.com/v1_1/<my_name>/image/upload'; 
    const apiKey = 'secret_key'; 
    const uploadPreset = 'test_preset'; 

    const data = new FormData(); 
    data.append('file', props.userImages[0]); 
    data.append('upload_preset', uploadPreset); 
    data.append('api_key', apiKey); 

    const xhr = new XMLHttpRequest(); 
    xhr.open('POST', cloudinaryURL, true); 
    xhr.send(data); 
    xhr.onReadyStateChange =() => { 
    if (xhr.readyState == 4 && xhr.status == 200) { 
     return JSON.parse(xhr.responseText); 
    } 
    }; 

    return xhr.onReadyStateChange(); 
} 

export function createReview(props) { 

const imageUrl = generateUrl(props); 

const mergedProps = //... 

    // Here I'd like to merge my newly generated 
    // url back into props before I post to my API like so... 

    const request = axios.post(`${REQUEST_URL}/api`, mergedProps) 
    return { 
    type: CREATE_REVIEW, 
    payload: request 
    } 
}; 

Toute aide est grandement appréciée.

+0

'XMLHttpRequest' n'est pas et ne concerne pas les promesses. Je ne comprends pas la question dans le contexte des promesses. – Sukima

+0

Lorsque j'envoie mes données de formulaire, je crois que je dois attendre mon XMLHttpRequest pour renvoyer un responseText si l'état prêt est 4 et le statut est 200 donc je sens que je ne peux pas retourner immédiatement car il doit attendre pour recevoir le état prêt et statut. Faites-moi savoir si c'est correct ou non. Merci! – hidace

+0

C'est correct mais cela n'a rien à voir avec les promesses. En outre, il ne récupère pas tout ce que vous avez besoin d'utiliser les rappels XHR. – Sukima

Répondre

1

Cela n'a rien à voir avec des promesses dans le contexte de votre exemple basé sur le code XMLHttpRequest.

L'hypothèse que vous faites est que le rappel assigné à onReadyStateChange fait quelque chose avec sa valeur de retour. A la place, tout ce qui revient de cette fonction est consciencieusement ignoré.

Ce que vous voulez, c'est passer la valeur par un autre rappel.

function generateUrl(props, callback) { 
    // Do things here 
    xhr.onReadyStateChange =() => { 
     if (xhr.readyState == 4 && xhr.status == 200) { 
     callback(JSON.parse(xhr.responseText)); 
     } 
    }; 
} 


generateUrl(props, (response) => { 
    const mergedProps = // Use response as expected. 
}); 

Puisque vous avez mentionné votre promesse et l'utilisation ES2015 nous pouvons convertir en utiliser effectivement des promesses qui est probablement ce que vous vouliez commencer.

function generateUrl(props) { 
    return new Promise((resolve, reject) => { 
    const cloudinaryURL = 'https://api.cloudinary.com/v1_1/<my_name>/image/upload'; 
    const apiKey = 'secret_key'; 
    const uploadPreset = 'test_preset'; 

    const data = new FormData(); 
    data.append('file', props.userImages[0]); 
    data.append('upload_preset', uploadPreset); 
    data.append('api_key', apiKey); 

    const xhr = new XMLHttpRequest(); 
    xhr.onReadyStateChange =() => { 
     if (xhr.readyState == 4) { 
     if (xhr.status == 200) { 
      resolve(xhr.responseText); 
     } else { 
      reject(new Error(`Failed HTTP request (${xhr.status})`)); 
     } 
    }; 
    xhr.onerror = reject; 

    xhr.open('POST', cloudinaryURL, true); 
    xhr.send(data); 
    }); 
} 

generateUrl(props) 
    .then(JSON.parse) 
    .then(results => { 
    // Do something with response 
    }) 
    .catch(error => { 
    // Do something with the error 
    });