Skip to content

Instantly share code, notes, and snippets.

@michaelcontento
Last active November 23, 2015 13:44
Show Gist options
  • Save michaelcontento/b1272b27e555c56e93ff to your computer and use it in GitHub Desktop.
Save michaelcontento/b1272b27e555c56e93ff to your computer and use it in GitHub Desktop.
'use strict';
var React = require('react/addons');
var PureRenderMixin = React.addons.PureRenderMixin;
var MAX_LOADING_TASKS = 3;
var loadingQueue = [];
var loadingQueueDirty = false;
var loadingTasks = 0;
function startLoadingTask() {
// enough jobs running
if (loadingTasks >= MAX_LOADING_TASKS) {
return;
}
// no job available
if (loadingQueue.length <= 0) {
return;
}
// sort queue only if neccessary
if (loadingQueueDirty) {
loadingQueueDirty = false;
loadingQueue.sort(function(a, b) {
return a.sortBy() - b.sortBy();
});
}
// helper to ensure loadingTasks is decremented
function startNextLoadingTask() {
loadingTasks -= 1;
// break nesting hierarchy
setTimeout(startLoadingTask, 0);
}
// pop job
loadingTasks += 1;
var job = loadingQueue.shift();
// check if the job need to be processed
if (!job.isActive()) {
return startNextLoadingTask();
}
// actual work
var img = new Image();
img.onload = function() {
job.onLoad();
startNextLoadingTask();
};
img.src = job.getSrc();
}
/**
* Example:
* <PreloadImage src="https://www.google.com/images/logos/url_shortener_logo.gif">
* Loading ...
* </PreloadImage>
*/
var PreloadImage = React.createClass({
mixins: [PureRenderMixin],
propTypes: {
src: React.PropTypes.string.isRequired,
children: React.PropTypes.element.isRequired,
preloadOrder: React.PropTypes.number,
},
getDefaultProps: function() {
return {
preloadOrder: 0,
};
},
getInitialState: function() {
return {
loaded: false,
};
},
componentDidMount: function() {
loadingQueue.push(this.getJob());
loadingQueueDirty = true;
setTimeout(startLoadingTask, 0);
},
getJob: function() {
var self = this;
return {
getSrc: function() {
return self.props.src;
},
isActive: function() {
return self.isMounted();
},
sortBy: function() {
return self.props.preloadOrder;
},
onLoad: function() {
if (self.isMounted()) {
self.setState({ loaded: true });
}
},
};
},
render: function() {
if (this.state.loaded) {
var imgProps = this.props;
delete imgProps.preloadOrder;
return(
<img {...imgProps} />
);
} else {
return this.props.children;
}
}
});
module.exports = PreloadImage;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment