Я не утверждаю, что несколько одновременных XHR стабильны, но это работает для меня в симуляторе.Этот вопрос был больше о конкретной задаче пользовательского интерфейса , независимо от того, стоят ли XHR в асинхронной очереди , но я ценю любые отзывы о качестве кода или лучших практиках.Вот решение, к которому я пришел.
// a namespace for the UI code
myApp.ui = {};
// a function for this window
myApp.ui.createCameraWindow = function() {
var win = Ti.UI.createWindow({
// I have my own custom header
title:'',
});
var containerView = Ti.UI.createView({
backgroundColor:'#85AAD7',
});
var tableQueue = Ti.UI.createTableView({
backgroundColor:'#85AAD7',
separatorColor:'#85AAD7',
data:photosQueue, // photosQueue is an empty global array
width:320
});
containerView.add(tableQueue);
// device stores the candidate file on the system and sends data
Ti.App.addEventListener('photoReady',function(candidate) {
// here we an add a caption if we please
var captionView = Ti.UI.createView({
backgroundColor:'#FFF'
});
var candidateIMG = Ti.UI.createImageView({
// the candidate file was stored with a uniqie identifier called fileStamp
// don't forget to change resourcesDirectory to tempDirectory for use on the device
image:Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory,candidate.fileStamp + '-thumb320.png'),
height:367,
width:320,
top:0,
opacity:0.5
});
var captionLabel = Ti.UI.createLabel({
text:'caption',
color:'#000',
top:-180,
textAlign:'center',
font:{fontSize:50,fontWeight:'bold',fontStyle:'italic',fontFamily:'Cochin'},
opacity:0.5
});
var captionBox = Ti.UI.createTextField({
height:35,
width:270,
textAlign:'center',
borderStyle:Titanium.UI.INPUT_BORDERSTYLE_ROUNDED
});
var submitButton = Ti.UI.createButton({
title:'Submit',
color:'#000',
selectedColor:'#FFF',
top:220,
width:130,
height:35
});
captionView.add(candidateIMG);
captionView.add(captionLabel);
captionView.add(captionBox);
captionView.add(submitButton);
// cover the table view with the temporary caption prompt
containerView.add(captionView);
submitButton.addEventListener('click',function(){
candidate.caption = captionBox.value;
// start the xhr send from another function
myApp.remote.createPhoto(candidate);
// go back to the table view
containerView.remove(captionView);
var tempFile = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory,candidate.fileStamp + '-thumb75.png');
var progressBar = Ti.UI.createProgressBar({
width:205,
height:50,
right:20,
min:0,
max:1,
value:0,
style:Titanium.UI.iPhone.ProgressBarStyle.PLAIN,
color:'#FFF'
});
var thisRow = Ti.UI.createTableViewRow({
backgroundColor:'#FFF',
layout:"vertical",
height:75,
fileStamp:candidate.fileStamp
});
// apparently the progress bar needs to be inside a view to align correctly
var nestedView = Ti.UI.createView({
height:75,
width:320
});
var tinyThumb = Ti.UI.createImageView({
image:tempFile,
height:75,
width:75,
left:0
});
nestedView.add(tinyThumb);
progressBar.show();
nestedView.add(progressBar);
thisRow.add(nestedView);
photosQueue.push(thisRow);
tableQueue.setData(photosQueue);
});
});
// the xhr.onsendstream will repeatedly fire this function and send an object containing an id and e.progress
Ti.App.addEventListener('streamProgress',function(upload) {
// loop through the global queue
for (i=0;i<photosQueue.length;i++) {
// find the the array object that corresponds to the upload object
if (photosQueue[i].fileStamp == upload.id) {
// identifiy this object as the tableRow in the UI
thisRow = photosQueue[i];
// find its progress bar by knowing the view hierarchy
var bar = thisRow.children[0].children[1];
// update the progress bar's value
bar.value = upload.progress;
// update the entire tableView with new data
tableQueue.setData(photosQueue);
}
}
});
// the xhr.onload will fire this function and send an object containing an id and a status code
Ti.App.addEventListener('confirmation',function(upload) {
// loop through the global queue
for (i=0;i<photosQueue.length;i++) {
// find the the array object that corresponds to the upload object
if (photosQueue[i].fileStamp == upload.id) {
// identifiy this object as the tableRow in the UI
thisRow = photosQueue[i];
// if the POST was successful
if (upload.status == '201') {
// then make the entire row pleasing
thisRow.backgroundColor = 'green';
} else {
// otherwise make it ugly
thisRow.backgroundColor = 'red';
}
// identify the full progress bar in the view hierarchy
var bar = thisRow.children[0].children[1];
// remove it regardless
thisRow.children[0].remove(bar);
// update the entire tableView with new data
tableQueue.setData(photosQueue);
}
}
});
win.add(containerView);
return win;
};