Kim*_*cks 5 javascript jquery promise sequential deferred
我打算使用jQuery上传一个文件数组.
这个意图包含在一个名为的函数中uploadFilesUsingAjax();
var uploadFilesPromise = uploadFilesUsingAjax();
$.when(uploadFilesPromise).done(function (uploadFilesAjaxResult) {
// redirect to success page...
Run Code Online (Sandbox Code Playgroud)
在做其他事情之前,我需要等待所有文件成功上传.
里面uploadFilesUsingAjax(),
我这样写了我的代码
function uploadFilesUsingAjax() {
var files = pages; // pages is a global variable which is an array of files
var url = "/users/" + currentUser.id + "/files.json";
var type = "POST";
console.info('files length:' + files.length);
if (files.length > 0) {
var promises=[];
for (var i = 0; i < files.length; i++) {
var data = new FormData();
var postData = {};
var file = files.getByIndex(i);
var key = i + 1;
if (typeof (file.id) !== "undefined" && file.id > 0) {
data.append(key, JSON.stringify(file));
} else {
data.append(key, file);
}
var request = $.ajax({
//this is the php file that processes the data
url: url,
//POST method is used
type: type,
//pass the data
data: data,
//Do not cache the page
cache: false,
xhr: function() {
// custom xhr
myXhr = $.ajaxSettings.xhr();
if(myXhr.upload) { // check if upload property exists
myXhr.upload.addEventListener('progress',updatePagesProgress, false); // for handling the progress of the upload
}
return myXhr;
},
// DO NOT set the contentType and processData
// see http://stackoverflow.com/a/5976031/80353
contentType: false,
processData: false,
//success
success: function (json) {
// json is already an object thanks to cakephp code to serialize
//if POST is a success expect no errors
if (json.error == null && json.result != null) {
currentUser = json.result.User;
// error
} else {
alert(json.error);
}
}
});
promises.push( request);
}
var promise = promises[0];
for (var i = 1; i < promises.length; i++) {
promise = promise.then(promises[i]);
}
return promise.done(function () { console.log('all!')});
Run Code Online (Sandbox Code Playgroud)
不幸的是,在重定向到成功页面之前,我无法上传大量文件.
我已经尝试了各种StackOverflow解决方案来解决这个问题.到目前为止没有任何作 请指教.
某些代码已被截断以节省空间.
你所有的承诺都是并行的,而不是连续的。
承诺代表一个已经运行的任务。与 C# 任务或其他抽象不同,JavaScript 中的 Promise 已经启动。表示尚未开始的任务的方法是返回一个 Promise 的函数。
因为promises[i]已经是一个承诺 - 当你promise.then(object)这样做时,它不会添加 .then 处理程序,而是立即返回。.then忽略任何不是函数的参数。
这就是为什么它返回得早,第一个承诺一兑现就返回。您也不需要.when. 创建一个创建上传过程的函数,如下所示:
function createUploadTask(file,i){
return function(){
var data = new FormData();
var postData = {};
var file = files.getByIndex(i);
var key = i + 1;
if (typeof (file.id) !== "undefined" && file.id > 0) {
data.append(key, JSON.stringify(file));
} else {
data.append(key, file);
}
return $.ajax({...}); // return the promise
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以将文件映射到任务:
var tasks = files.map(createUploadTask);
Run Code Online (Sandbox Code Playgroud)
请注意,现在每个任务都是通过文件上传返回承诺的函数。它们不是承诺。
现在,您可以链接它们:
var p = tasks[0](); // start off the chain
for(var i = 1; i < tasks.length; i++){
// chain the next task, note, that we're passing a _function_ here
// when you return a promise from a `.then` it will fulfill when that promise
// fulfills, in our case the $.ajax
p = p.then(tasks[i]);
}
return p;
Run Code Online (Sandbox Code Playgroud)
您现在也不需要使用when,因为您返回一个承诺。我假设您不需要这里的实际结果(而只是为了知道成功/失败)。
您只需执行以下操作:
function uploadFilesUsingAjax() {
// settings
if(tasks.length === 0){
// a method MUST always either return either synchronously or asynchronously never
// both, always return a promise. Otherwise you get API hell.
var d = $.Deferred();
d.reject(new Error("Called uploadFiles with no files to upload"));
return d.promise;
}
tasks = pages.map(createUploadTask)
var p = tasks[0](); // call first one
for(var i = 1; i < tasks.length; i++) p = p.then(tasks[i]);
return p;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1602 次 |
| 最近记录: |