运行 具有异步事件的另一个函数完成时的一个函数
run a function when another function with an asynchronous event completes
我正在制作一个动态 canvas 动画,它将加载多个图像并制作动画。
我似乎 运行 进入了竞争状态,我不知道如何解决它。
此对象构造函数加载图像,为它们创建对象,并将宽度和高度变量设置为自然图像大小的 1/2。
window.imgWidth;
window.imgHeight;
//array to hold character objects
window.character = [];
window.characterPosition;
function Character(name, x, y){
//define the image object within the Character
this.imageObject = new Image();
this.imageObject.src = 'data:text/javascript;base64,'+name;
window.character.push(this);
window.characterPosition = window.character.indexOf(this);
//set natural width and natural height once the image is loaded
//conditional used by Chrome
if (this.imageObject.addEventListener){
this.imageObject.addEventListener('load', function(){
window.imgWidth = this.naturalWidth/2;
window.imgHeight = this.naturalHeight/2;
//set natural width and natural height to object
window.character[characterPosition]['imageObject']['w'] = window.character[characterPosition]['imageObject']['w0'] = window.imgWidth;
window.character[characterPosition]['imageObject']['h'] = window.character[characterPosition]['imageObject']['h0'] = window.imgHeight;
//set initial x and y position
window.character[characterPosition]['imageObject']['x1'] = x;
window.character[characterPosition]['imageObject']['y1'] = y;
//set loaded property for the object once loading is done
window.character[characterPosition]['imageObject']['loaded'] = true;
console.log(characterPosition);
console.log(window.character[characterPosition]['imageObject']);
function imageLoaded(element, index, array){
return element['imageObject']['loaded'] == true;
}
//test whether every object in array has the image loaded
if(character.every(imageLoaded)){
$('button#play').show();
};
});
}
} //end object constructor
准备好内部文档,我正在使用此对象构造函数创建两个对象。
var sun0 = new Character('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAW0lEQVR42mL8//8/AzpgZGTcC6KBcs5wMRwK/0MVMsLEmLAoEmXAApiwiKUhaRJCltgLsQVsWwIQ/wTx0fBeRigD7B6Y24i1mj4Kn4KI7Uie2Y7FI8+B2AMgwABjRynfWgpcxQAAAABJRU5ErkJggg==', 12, 12);
var sun1 = new Character('R0lGODlhCgAKANUCAEKtP0StQf8AAG2/a97w3qbYpd/x3mu/aajZp/b79vT69MnnyK7crXTDcqraqcfmxtLr0VG0T0ivRpbRlF24Wr7jveHy4Pv9+53UnPn8+cjnx4LIgNfu1v///37HfKfZpq/crmG6XgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAKAAoAAAZIQIGAUDgMEASh4BEANAGAxRAaaHoYAAPCCZUoOIDPAdCAQhIRgJGiAG0uE+igAMB0MhYoAFmtJEJcBgILVU8BGkpEAwMOggJBADs=',0,0);
问题在于,由于this.imageObject.addEventListener('load', function(){
是异步的,运行每次对象构造函数运行的console.log
消息都显示来自第二个对象的信息.我希望第一组显示第一个对象的信息,第二组显示第二个对象的信息。
//First set, run by sun0
console.log(characterPosition); //1
console.log(window.character[characterPosition]['imageObject']); //info for sun1
//Second set, run by sun1
console.log(characterPosition); //1
console.log(window.character[characterPosition]['imageObject']); //info for sun1
我可以通过像这样设置计时器来解决这个问题:
var sun0 = new Character('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAW0lEQVR42mL8//8/AzpgZGTcC6KBcs5wMRwK/0MVMsLEmLAoEmXAApiwiKUhaRJCltgLsQVsWwIQ/wTx0fBeRigD7B6Y24i1mj4Kn4KI7Uie2Y7FI8+B2AMgwABjRynfWgpcxQAAAABJRU5ErkJggg==', 12, 12);
window.setTimeout(slowLoad, 2000);
function slowLoad(){
var sun1 = new Character('R0lGODlhCgAKANUCAEKtP0StQf8AAG2/a97w3qbYpd/x3mu/aajZp/b79vT69MnnyK7crXTDcqraqcfmxtLr0VG0T0ivRpbRlF24Wr7jveHy4Pv9+53UnPn8+cjnx4LIgNfu1v///37HfKfZpq/crmG6XgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAKAAoAAAZIQIGAUDgMEASh4BEANAGAxRAaaHoYAAPCCZUoOIDPAdCAQhIRgJGiAG0uE+igAMB0MhYoAFmtJEJcBgILVU8BGkpEAwMOggJBADs=',0,0);
}
这按预期工作。
//First set, run by sun0
console.log(characterPosition); //0
console.log(window.character[characterPosition]['imageObject']); //info for sun0
//Second set, run by sun1
console.log(characterPosition); //1
console.log(window.character[characterPosition]['imageObject']); //info for sun1
但很明显,我不想为了让 sun1 的功能仅在 sun0 完成后才 运行 引入手动延迟。如何在sun0完成其功能(包括异步部分)后立即将var sun1
变为运行?请记住,我也会对其他几张(大约 15 张)图像执行此操作。
可能有更好的方法,但我用一个函数解决了这个问题,该函数中有一堆条件语句,以查看是否在 运行 创建该对象的函数之前定义了一个对象。
function loadImages(){
if (!character[0]){
var sun0 = new Character('sun0', sunParent.x, sunParent.y);
} else if (!character[1]){
var sun1 = new Character('sun1', sunParent.x, sunParent.y);
} else if (!character[2]){
var sun2 = new Character('sun2', sunParent.x, sunParent.y);
} else if (!character[3]){
var bed = new Character('bed', 50, 500);
} else if (!character[4]){
var bed = new Character('plant1', 480, 490);
} else if(character.every(imageLoaded)){
$('button#play').show();
}
//test whether every object in array has the image loaded
function imageLoaded(element, index, array){
return element['imageObject']['loaded'] == true;
}
}
我最初在文档准备就绪时调用 loadImages();
,并在加载图像的异步部分的末尾的字符构造中调用它。
我正在制作一个动态 canvas 动画,它将加载多个图像并制作动画。
我似乎 运行 进入了竞争状态,我不知道如何解决它。
此对象构造函数加载图像,为它们创建对象,并将宽度和高度变量设置为自然图像大小的 1/2。
window.imgWidth;
window.imgHeight;
//array to hold character objects
window.character = [];
window.characterPosition;
function Character(name, x, y){
//define the image object within the Character
this.imageObject = new Image();
this.imageObject.src = 'data:text/javascript;base64,'+name;
window.character.push(this);
window.characterPosition = window.character.indexOf(this);
//set natural width and natural height once the image is loaded
//conditional used by Chrome
if (this.imageObject.addEventListener){
this.imageObject.addEventListener('load', function(){
window.imgWidth = this.naturalWidth/2;
window.imgHeight = this.naturalHeight/2;
//set natural width and natural height to object
window.character[characterPosition]['imageObject']['w'] = window.character[characterPosition]['imageObject']['w0'] = window.imgWidth;
window.character[characterPosition]['imageObject']['h'] = window.character[characterPosition]['imageObject']['h0'] = window.imgHeight;
//set initial x and y position
window.character[characterPosition]['imageObject']['x1'] = x;
window.character[characterPosition]['imageObject']['y1'] = y;
//set loaded property for the object once loading is done
window.character[characterPosition]['imageObject']['loaded'] = true;
console.log(characterPosition);
console.log(window.character[characterPosition]['imageObject']);
function imageLoaded(element, index, array){
return element['imageObject']['loaded'] == true;
}
//test whether every object in array has the image loaded
if(character.every(imageLoaded)){
$('button#play').show();
};
});
}
} //end object constructor
准备好内部文档,我正在使用此对象构造函数创建两个对象。
var sun0 = new Character('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAW0lEQVR42mL8//8/AzpgZGTcC6KBcs5wMRwK/0MVMsLEmLAoEmXAApiwiKUhaRJCltgLsQVsWwIQ/wTx0fBeRigD7B6Y24i1mj4Kn4KI7Uie2Y7FI8+B2AMgwABjRynfWgpcxQAAAABJRU5ErkJggg==', 12, 12);
var sun1 = new Character('R0lGODlhCgAKANUCAEKtP0StQf8AAG2/a97w3qbYpd/x3mu/aajZp/b79vT69MnnyK7crXTDcqraqcfmxtLr0VG0T0ivRpbRlF24Wr7jveHy4Pv9+53UnPn8+cjnx4LIgNfu1v///37HfKfZpq/crmG6XgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAKAAoAAAZIQIGAUDgMEASh4BEANAGAxRAaaHoYAAPCCZUoOIDPAdCAQhIRgJGiAG0uE+igAMB0MhYoAFmtJEJcBgILVU8BGkpEAwMOggJBADs=',0,0);
问题在于,由于this.imageObject.addEventListener('load', function(){
是异步的,运行每次对象构造函数运行的console.log
消息都显示来自第二个对象的信息.我希望第一组显示第一个对象的信息,第二组显示第二个对象的信息。
//First set, run by sun0
console.log(characterPosition); //1
console.log(window.character[characterPosition]['imageObject']); //info for sun1
//Second set, run by sun1
console.log(characterPosition); //1
console.log(window.character[characterPosition]['imageObject']); //info for sun1
我可以通过像这样设置计时器来解决这个问题:
var sun0 = new Character('iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAW0lEQVR42mL8//8/AzpgZGTcC6KBcs5wMRwK/0MVMsLEmLAoEmXAApiwiKUhaRJCltgLsQVsWwIQ/wTx0fBeRigD7B6Y24i1mj4Kn4KI7Uie2Y7FI8+B2AMgwABjRynfWgpcxQAAAABJRU5ErkJggg==', 12, 12);
window.setTimeout(slowLoad, 2000);
function slowLoad(){
var sun1 = new Character('R0lGODlhCgAKANUCAEKtP0StQf8AAG2/a97w3qbYpd/x3mu/aajZp/b79vT69MnnyK7crXTDcqraqcfmxtLr0VG0T0ivRpbRlF24Wr7jveHy4Pv9+53UnPn8+cjnx4LIgNfu1v///37HfKfZpq/crmG6XgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAIALAAAAAAKAAoAAAZIQIGAUDgMEASh4BEANAGAxRAaaHoYAAPCCZUoOIDPAdCAQhIRgJGiAG0uE+igAMB0MhYoAFmtJEJcBgILVU8BGkpEAwMOggJBADs=',0,0);
}
这按预期工作。
//First set, run by sun0
console.log(characterPosition); //0
console.log(window.character[characterPosition]['imageObject']); //info for sun0
//Second set, run by sun1
console.log(characterPosition); //1
console.log(window.character[characterPosition]['imageObject']); //info for sun1
但很明显,我不想为了让 sun1 的功能仅在 sun0 完成后才 运行 引入手动延迟。如何在sun0完成其功能(包括异步部分)后立即将var sun1
变为运行?请记住,我也会对其他几张(大约 15 张)图像执行此操作。
可能有更好的方法,但我用一个函数解决了这个问题,该函数中有一堆条件语句,以查看是否在 运行 创建该对象的函数之前定义了一个对象。
function loadImages(){
if (!character[0]){
var sun0 = new Character('sun0', sunParent.x, sunParent.y);
} else if (!character[1]){
var sun1 = new Character('sun1', sunParent.x, sunParent.y);
} else if (!character[2]){
var sun2 = new Character('sun2', sunParent.x, sunParent.y);
} else if (!character[3]){
var bed = new Character('bed', 50, 500);
} else if (!character[4]){
var bed = new Character('plant1', 480, 490);
} else if(character.every(imageLoaded)){
$('button#play').show();
}
//test whether every object in array has the image loaded
function imageLoaded(element, index, array){
return element['imageObject']['loaded'] == true;
}
}
我最初在文档准备就绪时调用 loadImages();
,并在加载图像的异步部分的末尾的字符构造中调用它。