Javascript 加载所有图像时解析承诺
我使用以下代码预加载图像:Javascript 加载所有图像时解析承诺,javascript,angularjs,angular-promise,Javascript,Angularjs,Angular Promise,我使用以下代码预加载图像: function preLoad() { var deferred = $q.defer(); var imageArray = []; for (var i = 0; i < $scope.abbreviations.length; i++) { imageArray[i] = new Image(); imageArray[i].src = $scope.
function preLoad() {
var deferred = $q.defer();
var imageArray = [];
for (var i = 0; i < $scope.abbreviations.length; i++) {
imageArray[i] = new Image();
imageArray[i].src = $scope.abbreviations[i].imgPath;
}
imageArray.forEach.onload = function () {
deferred.resolve();
console.log('Resolved');
}
imageArray.forEach.onerror = function () {
deferred.reject();
console.log('Rejected')
}
return deferred.promise;
}
preLoad();
这是可行的,但我想了解:
$q.all
来确保在解析承诺之前加载所有图像这些有点神秘。我不习惯使用这个库,但其想法如下:
function getImagePromise(imgData) {
var imgEl = new Image();
imgEl.src = imgData.imgPath;
return $q(function(resolve, reject){
imgEl.addEventListener('load', function(){
if ((
'naturalHeight' in this
&& this.naturalHeight + this.naturalWidth === 0
)
|| (this.width + this.height == 0)) {
reject(new Error('Image not loaded:' + this.src));
} else {
resolve(this);
}
});
imgEl.addEventListener('error', function(){
reject(new Error('Image not loaded:' + this.src));
});
})
}
function preLoad() {
return $q.all($scope.abbreviations.map(getImagePromise));
}
// using
preLoad().then(function(data){
console.log("Loaded successfully");
data.map(console.log, console);
}, function(reason){
console.error("Error loading: " + reason);
});
看看这个
你的职能:
function preLoad() {
var promises = [];
function loadImage(src) {
return $q(function(resolve,reject) {
var image = new Image();
image.src = src;
image.onload = function() {
console.log("loaded image: "+src);
resolve(image);
};
image.onerror = function(e) {
reject(e);
};
})
}
$scope.images.forEach(function(src) {
promises.push(loadImage(src));
})
return $q.all(promises).then(function(results) {
console.log('promises array all resolved');
$scope.results = results;
return results;
});
}
这个想法与Henrique的答案非常相似,但onload处理程序用于解析每个承诺,onerror用于拒绝每个承诺
回答您的问题:
1) 承诺工厂
$q(function(resolve,reject) { ... })
构建一个承诺。传递给resolve
函数的任何内容都将在then
函数中使用。例如:
$q(function(resolve,reject) {
if (Math.floor(Math.random() * 10) > 4) {
resolve("success")
}
else {
reject("failure")
}
}.then(function wasResolved(result) {
console.log(result) // "success"
}, function wasRejected(error) {
console.log(error) // "failure"
})
2) $q.all被传递一个承诺数组,
然后
接受一个函数,该函数被传递一个具有所有原始承诺分辨率的数组。你从哪里得到这个imageArray.forEach.onload
的?@HenriqueBarcelos你的意思是它应该是imageArray.onload
吗?我想知道你为什么要谈论“第一个承诺“…您的第一个代码片段中只有一个承诺。我认为您的第二个代码不起作用。是的,它确实会记录最后一条消息,但记录得太早了。此代码中没有任何地方您正在等待加载
或错误
事件,我非常确信,$q.when
在传递图像时不会自动执行此操作,这两种方法都不起作用。您是否故意遗漏了添加onerror
处理程序?您的意思是Image
元素的onerror
处理程序?只有当响应状态与200
不同。对于可以返回200
状态,但响应内容(mime)不是图像的情况,我在文章中使用的方法是防弹的。这是相关的。是的,但是当返回no 200状态时会触发afaik(以及我如何理解)noload
事件-在某些情况下,只会触发error
。您是对的,因此稳健的解决方案必须包括这两种方法。我会修改答案,我看不出有什么区别。“但是onload处理程序用于解析每个承诺,onerror用于拒绝每个承诺”是什么意思?顺便说一句,你应该在你的答案中发布你的代码,尤其是loadImage
函数,而不是在某个插件上。很好,你说得对&它是经过编辑的。为了回答您的问题,我相信onerror处理程序可以决定是否拒绝,而不是在onload处理程序中决定解决/拒绝。onload处理程序只能解析。取决于用例,但是如果您需要更细粒度的拒绝标准,则其他解决方案可能更好。另外,我想更深入地向奥帕解释承诺,对吧。请注意,Henrique也必须解决这个问题,有关详细信息,请参见其答案上的评论:-)@ShaharZ感谢您的努力。乍一看,你的片段比亨里克的更清晰。我也要试一试+1.@ShaharZ在链接函数console.log(newVal,oldVal)中代码>返回未定义,未定义
。
$q(function(resolve,reject) {
if (Math.floor(Math.random() * 10) > 4) {
resolve("success")
}
else {
reject("failure")
}
}.then(function wasResolved(result) {
console.log(result) // "success"
}, function wasRejected(error) {
console.log(error) // "failure"
})