问题
I have an RSAA (Redux Standard API-calling Action) that I'm using to retrieve image/jpeg content. All the examples I've seen deal with JSON data so I copied the getJSON function and implemented my own getImage function to deal with this content type. The problem I'm now running into is that this blob needs to be converted to base64 and that has to be done using an async function. So, my FSA gets triggered before this async operation completes.
I suspect that I need to somehow piggyback on the existing promise chain in the RSAA payload processing but I'm not sure how to do this.
Here's the snippet of code with the line commented where I need to perform the promise resolve to return this result:
export function fetchSiteThumbnailImage(endpoint) {
return {
[CALL_API]: {
endpoint,
method: 'GET',
headers: {
'Accept': 'image/jpeg'
},
types: [
LOAD_SITE_THUMBNAIL_REQUEST,
{
type: LOAD_SITE_THUMBNAIL_SUCCESS,
payload: (action, state, res) => {
return getImage(res).then((blob) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
const base64data = reader.result;
return base64data; // this needs to "resolve" - how??
}
});
},
meta: (action, state, res) => {
return {
siteId,
endpoint
}
}
},
LOAD_SITE_THUMBNAIL_FAILURE
]
}
}
}
Thanks!
回答1:
You have to wrap your FileReader logic into a Promise:
function readAsBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => {
const base64data = reader.result;
resolve(base64data);
}
reader.onerror = (err) => {
reject(err);
}
reader.readAsDataURL(blob);
});
}
Your payload function can then just be
(action, state, res) => getImage(res).then(readAsBase64);
A couple of notes:
reader.onloadendgets called when the reading operation is completed (either in success or in failure), whilereader.onloadis called only on successful completion andreader.onerroronly on failed completion — you want to separate the two cases.You should set the event handlers before you start reading the blob to avoid race conditions — so put
reader.readAsDataURLat the end.
回答2:
I have managed to solve this so I'll answer my own question... I just needed to return a new Promise object like this:
return new Promise((resolve, reject) => {
getImage(res).then((blob) => {
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = () => {
const base64data = reader.result;
resolve(base64data);
}
reader.onerror = () => {
reject(Error('unable to process image/jpeg blob'));
}
})
});
来源:https://stackoverflow.com/questions/38818782/using-redux-api-middleware-to-process-image-jpeg-content