背景
我正在构建一个Angular应用程序,其中列出了在给定地址注册的公司。
提供一些背景信息...
假设我有3家公司:A公司,B公司和C公司。
公司B与公司A的注册地址相同。公司C不是。
当我导航至该应用并在公司A上进行过滤时,我希望仅在列表中看到公司B。
问题
我的问题不是我无法正常工作,而是太慢了!我需要以某种方式利用多线程/并发。
为了弄清楚在给定地址注册了哪些公司,我必须进行几次HTTP调用。
在解释我进行HTTP调用的顺序之前。让我向您展示API的外观:
function send_counter(counter) {
$.ajax({
url : "index.php",
type : "POST",
cache : false,
data : { counter : counter, submit: 1 }
});
}
});
对,这是顺序:
当前实施
<?php
if (isset($_POST['submit'])){
$counter=$_POST['counter'];
echo "$counter";
}
?>
必须有一个更优雅/性能更高的解决方案!
任何帮助将不胜感激:)
谢谢
本
答案 0 :(得分:1)
您是正确的,因为这些API调用中的每个调用都必须先等待另一个完成。
您本身无权使用多线程,但是您可以在编写时使用Promise.all
使其并发。具体来说,您可以同时检索地址和链接,然后同时检索所有其他地址。我已经缩短了一些方法调用名称,以便于编写:
const [companyAAddress, companyALinks] = await Promise.all(
getAddress(id).toPromise(),
getLinks(id).toPromise(),
);
const companiesToShow = await Promise.all(links.map(link => getAddress(link.id).pipe(
map(linkAddress => [link, linkAddress]),
filter(([, { id }]) => id === companyAAddress.id),
).toPromise())
您可以严格使用Observables来做到这一点,而不是使用promises。
forkJoin(getAddress(id), getLinks(id)).pipe(
mergeMap(([companyAAddress, companyALinks]) => companyALinks.map(link => getAddress(link.id).pipe(
map(linkAddress => [link, linkAddress]),
filter(([, { id }]) => id === companyAAddress.id),
))
)
但是,我要说的是,服务器应该实现从单个请求中获取链接公司的功能。
答案 1 :(得分:0)
您应该在这里考虑其他布局。
选项1
将该业务逻辑移至服务器端。从问题的描述中,我看不到客户端以任何方式简化了检索B地址的过程。服务器端拥有检索所有链接地址所需的所有信息。
您只需要一个电话到后端。而且您可以在这里避免使用await
,如果服务器无法快速响应,这会使用户的触觉也变慢。
服务器端的伪代码:
// this is a new endpoint on the backend which holds your current client logic
on(/api/companies/<company>/address_links) {
// retrieve the address with it's id like your first endpoint and store it temporary in address/id
address = getCompanyAddress(company);
// query all all addresses with that id/address and store it in links[]
other_companies[] = getCompaniesWithAddress(address);
// Build your response JSON
return_me = {
id: address.id,
addressLine1: address.line1,
links: other_companies
}
// send the response
response.send(return_me);
}
选项2
重新设计后端,并使用websocket加快查询速度。您还可以避免同时HTTP请求的限制(每个服务仅一个请求)。
如果连接尚未建立,但是Websocket对于单个请求的速度可能会慢一些,但开销却比几个HTTP请求小得多。可以在这里找到非常好的文章(来自一个名为FeathersJS的非常好的框架的作者):https://blog.feathersjs.com/http-vs-websockets-a-performance-comparison-da2533f13a77您更改组件代码以监听观察者
this.subscription = this.myService.addressObserver$.subscribe((data: any) => {
[Assign and do something]
}
并更改服务以使用套接字(不完整且不可运行,仅是示例):
import * as feathers from '@feathersjs/client';
import * as io from 'socket.io-client';
[...]
@Injectable()
export class MyService {
private readonly feathersService: any;
public myObserver$: Subject<any>;
constructor() {
const socket = io(<url>, {
transports: ['websocket'],
forceNew: true,
});
const feathersApp = feathers().configure(feathers.socketio(socket));
this.feathersService = feathersApp.service('api/address');
// on (create, delete, update) methods work like realtime when something changed on the server
this.feathersService.on('updated', (address) => this.onUpdated(address));
}
// single find, can be adapted to query by something
public find(): void {
// the actual query to the server
this.feathersService.find(address).then((addresses: any) => {
this.myObserver$.next(addresses.data);
});
}
...
选项3
两者都做