- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
更新:答案结尾的完整解决方案。
像这样的代码:
@Injectable()
export class FileUploader {
constructor(private http: Http) {}
upload(url: string, file: File) {
let fileReader: FileReader = new FileReader();
return new Promise((resolve, reject) => {
fileReader.onloadend = (e) => {
// you can perform an action with read data here
let content = fileReader.result;
console.log('starting upload');
return this.http.post(url, content)
.map((res) => res.json()).toPromise();
};
fileReader.readAsArrayBuffer(file);
});
}
和用法类似
this.fileuploader.upload('/backend/upload', content).then(); // do something
但是当用户选择很多文件时(比如在 FB 上创建相册),所有文件会同时上传,从而完全阻塞浏览器。
我的计划是在一些属性中放置一组 promise ,另一个私有(private)方法将触发第一个;完成后,promise 将再次调用该方法,以便开始新的上传,直到所有完成。
我尝试的所有组合都失败了,我什至无法编译它们。即使上面的代码也不是我的,而是从其他问题中摘录的。
如何做到这一点?
已编辑:根据@toskv 的回答,这是我现在使用的解决方案。我更新了答案以防其他人遇到同样的问题。
再次感谢@toskv 的帮助。
@Injectable()
export class FileUploader {
private currentTask: Promise<any> = null;
constructor(private http: Http) {}
upload(url: string, file: File) {
let action = () => {
return new Promise((resolve) => {
let fileReader: FileReader = new FileReader();
fileReader.onloadend = (e) => {
let content = fileReader.result;
return this.http.post(url, content)
.map((res) => res.json()).toPromise()
.then((json) => {
resolve(json);
});
};
fileReader.readAsArrayBuffer(file);
})
};
return this.doNext(action)
}
private doNext(action: () => Promise<any>): Promise<any> {
if (this.currentTask) {
// if something is in progress do it after it is done
this.currentTask = this.currentTask.then(action);
} else {
// if this is the only action do it now
this.currentTask = action();
}
return this.currentTask;
}
}
最佳答案
如果您将调用包装在一个函数中,您可以像这样轻松地包装它们。
function chain(calls: Array<() => Promise<any>>): Promise<any> {
return calls.reduce((previous, current) => {
return previous.then(current);
}, Promise.resolve(""));
}
此函数的作用是遍历整个 promise 列表(它从 Promise.resolve 创建的已解决的 promise 开始)并将收到的 promise 列表中的每个函数添加为 then结果 promise 的回调。
这相当于这样做:
Promise
.resolve("")
.then(first)
.then(second);
一个如何使用它的例子。
let first = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('first');
resolve();
}, 3000);
})
}
let second = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('second');
resolve();
}, 100);
})
}
chain([first, second]);
您可以找到一个工作示例 here .
您还可以从这样的项目数组轻松创建 promise 返回函数列表。
let files = ['a', 'b', 'c'];
function uploadFile(file) {
return Promise.resolve<any>('v');
}
let uploads = files.map((file) => () => uploadFile(file))
chain(uploads);
按照我们在聊天中的讨论。看起来您真正需要的是一种可以对传入请求进行排队的服务。这是一个普通 typescript 的例子。您应该能够用 @Inject 对其进行注释,并按原样在您的文件上传服务中使用它。
class QueuedDispacherService {
private currentTask: Promise<any> = null;
constructor() { }
doNext(action: () => Promise<any>) {
if (this.currentTask) {
//if something is in progress do it after it is done
this.currentTask = this.currentTask.then(action);
} else {
if this is the only action do it now
this.currentTask = action();
}
return this.currentTask;
}
}
let dispatcher = new QueuedDispacherService();
let action1 = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('first task done!');
resolve('done 1!');
}, 10000);
})
}
let action2 = () => {
return new Promise((resolve) => {
setTimeout(() => {
console.log('second task done!');
resolve('done 2!');
}, 300);
})
}
dispatcher.doNext(action1);
dispatcher.doNext(action2);
您可以创建的 Action 函数与前面的示例相同。
和here它正在工作。
有了这个,您还可以通过订阅 doNext 方法返回的 promise 来收听每个上传。
dispatcher.doNext(action1).then((result) => console.log(result));
dispatcher.doNext(action2).then((result) => console.log(result));
如果您使用已解决的 promise 初始化 currentTask,则可以缩短代码。
class QueuedDispacherService {
private currentTask: Promise<any> = Promise.resolve();
constructor() { }
doNext(action: () => Promise<any>) {
return this.currentTask = this.currentTask.then(action);
}
}
此图显示了运行时发生的情况。最后,Promise API 所做的一切都是为了帮助您更优雅地处理回调。
关于angular - 如何逐个调用api而不是并发调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46000753/
我尝试在 d3.js 中进行链式转换。为此,我在数组中定义了一组转换,并(尝试)创建一个函数以使用 .each("end", function()) 递归调用它们,以在前一个为完成,但我还没有结果。
我是一名优秀的程序员,十分优秀!