译者:郭培
使用JavaScript Promises实现简单的Loader
原文链接:davidwalsh.name/javascript-…
我使用JavaScript加载器已经有几年了;无论是Dojo Loader,curl.js,还是使用 jQuery做为JavaScript loader,加载一组资源,一旦这些资源加载完成就给出响应,这是超级实用的。每个JavaScript loader都是功能强大,高效的,创建loader时浏览器不支持Promise API,loader可以代替Pormise API完成类似的工作。接下来的loader不属于该类型。
这个超级简单的loader使用 Promise API,成功或失败时触发回调,允许加载图片,CSS和javascript文件。这个小小的 ""loader"" (甚至不能称之为loader)不做:
- 缓存结果 (虽然这很容易)
- 提供一个模板/对象的返回
- 做Ajax调用 (虽然 XHR-to-Promise shim是可用的, 或者你可以使用 fetch)
- ... 或其他高级的东东
这是小小的""loader""的所有荣耀:
var load = (function() {
// 返回一个函数的函数: https://davidwalsh.name/javascript-functions
function _load(tag) {
return function(url) {
// 这个promise使用Promise.all确定成功或失败
return new Promise(function(resolve, reject) {
var element = document.createElement(tag);
var parent = 'body';
var attr = 'src';
// promise重要的成功和失败
element.onload = function() {
resolve(url);
};
element.onerror = function() {
reject(url);
};
// 需要根据标签类型设置不同的属性
switch(tag) {
case 'script':
element.async = true;
break;
case 'link':
element.type = 'text/css';
element.rel = 'stylesheet';
attr = 'href';
parent = 'head';
}
// 注入文件以启动加载
element[attr] = url;
document[parent].appendChild(element);
});
};
}
return {
css: _load('link'),
js: _load('script'),
img: _load('img')
}
})();
// 用法: 用一个回调加载不同的文件类型
Promise.all([
load.js('lib/highlighter.js'),
load.js('lib/main.js'),
load.css('lib/highlighter.css'),
load.img('images/logo.png')
]).then(function() {
console.log('Everything has loaded!');
}).catch(function() {
console.log('Oh no, epic failure!');
});
load对象提供了js, css, 和 img函数,这些函数都可以接受一个URL并加载这个URL。每个函数都会返回一个Promise,资源标签的 onload 或 onerror 事件会触发对应promise的resolve 或 reject。Promise.all使这些资源集中加载,这些资源都加载成功会触发then,这些资源中有任何一个没有加载成功就会触发catch。
我要强调的是,这是一个非常非常简单的""loader"";请不要评论为什么它没有其他加载器的花里胡哨的功能。 Promise API 使异步资源加载可管理,还有ServiceWorker API和fetch API,这些都是我喜欢的非常棒的API。如果你想帮自己,那就来看看这些超酷的API吧!