问题
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.onloadend
gets called when the reading operation is completed (either in success or in failure), whilereader.onload
is called only on successful completion andreader.onerror
only 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.readAsDataURL
at 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