gpt4 book ai didi

angular - 如何逐个调用api而不是并发调用

转载 作者:搜寻专家 更新时间:2023-10-30 21:29:07 25 4
gpt4 key购买 nike

更新:答案结尾的完整解决方案。


像这样的代码:

@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 所做的一切都是为了帮助您更优雅地处理回调。

enter image description here

关于angular - 如何逐个调用api而不是并发调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46000753/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com