我正在尝试上传图片列表。我将图像存储在一个数组中(称为图像)。
我在屏幕上显示预览。
我想要做的是按顺序上传它们,当它们完成上传时,我想设置一个标志。设置此标志时(由于Knockout的强大功能),图像将从列表中消失。
但是,我认为由于post命令的异步特性......我没有达到预期的效果。
以下是我要做的事情:
for(var i = 0; i < self.images().length; i++) {
var photo = self.images()[i];
var thisItem = photo;
var object = JSON.stringify({
Image: thisItem.Image,
AlbumID: albumId,
Filesize: thisItem.Filesize,
Filetype: thisItem.Filetype,
Description: thisItem.Description,
UniqueID: thisItem.UniqueID
});
var uri = "/api/Photo/Upload";
$.post({
url: uri,
contentType: "application/json"
}, object).done(function(data) {
if(data.IsSuccess) {
photo.Status(1);
}
}).fail(function() {
// Handle here
}).always(function() {
remainingImages = remainingImages - 1;
if(remainingImages == 0) self.isUploading(false);
});
}
self.isUploading(false);
但我认为正在发生的事情是for循环在所有帖子收到回复之前结束。因为在线删除了一张图片。
我尝试使用async: false
ajax帖子,但这会锁定屏幕然后它们都消失了。
我认为“完成”方法只会在帖子完成后执行,但我认为整个方法只在发送了post命令后才结束,然后我就永远不会得到done
。
我如何实现我想要做的...在帖子得到答复后设置每个图像的状态?
答案 0 :(得分:3)
你的第一个问题是你丢失了你认为对每个photo
对象的引用,因为循环在你的AJAX调用返回之前完成,所以当它们返回时,photo
是一个引用到self.images()
中的最后一项。
我们需要做的就是为循环的每次迭代创建一个 new 范围,每个范围都有自己对特定photo
的引用。 JavaScript具有函数范围,因此我们可以通过将每个photo
传递给函数来实现我们的目标。我将使用Immediately Invoked Function Expression (IIFE)作为示例:
for (var i = 0; i < self.images().length; i++) {
var photo = self.images()[i];
(function (thisItem) {
/* Everything else from within your for loop goes here. */
/* Note: the done handler must reference `thisItem`, not `photo`. */
})(photo);
}
请注意,您应该从最后一行删除self.isUploading(false);
。在所有POST请求都返回之前,不应将其设置为false。
我创建了一个功能齐全的小提琴,你可以看到here。
但是,此解决方案不会按顺序执行POST请求&#34;。我不确定你为什么要在发送下一个POST之前等待一个POST返回,因为这只会增加用户必须等待的时间。但为了完整起见,我将解释如何做到这一点。
要在上一次POST返回后触发POST,您需要删除for循环。您将需要一种方法来调用上一个POST的always
处理程序中的下一个POST。这是recursive函数的一个很好的候选者。
在我的解决方案中,我使用index
来跟踪images
上次发布的项目。我递归调用函数对images
中的下一个项目执行POST,直到我们在images
中发布了所有项目。以下代码替换for循环:
(function postNextImage (index) {
var photo = self.images()[i];
var thisItem = photo;
var object = JSON.stringify({
Image: thisItem.Image,
AlbumID: albumId,
Filesize: thisItem.Filesize,
Filetype: thisItem.Filetype,
Description: thisItem.Description,
UniqueID: thisItem.UniqueID
});
var uri = "/api/Photo/Upload";
$.post({
url: uri,
contentType: "application/json"
}, object)
.done(function (data) {
if(data.IsSuccess) {
thisItem.Status(1);
}
})
.fail(function () {
// Handle here
})
.always(function () {
if (index < (self.images().length - 1)) {
index += 1;
postNextImage(index);
} else {
self.isUploading(false);
}
});
})(0);
我也创建了这个解决方案的小提琴,可以找到here。