优化
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { fetchLinkPreview } from '../fetchLinkPreview';
|
||||
|
||||
const mockGetLinkPreviewFn = jest.fn();
|
||||
jest.mock('link-preview-js', () => ({
|
||||
getLinkPreview: async () => {
|
||||
mockGetLinkPreviewFn();
|
||||
},
|
||||
}));
|
||||
|
||||
describe('Test "fetchLinkPreview"', () => {
|
||||
test(
|
||||
'fetchLinkPreview should merge same request',
|
||||
async () => {
|
||||
await Promise.all([
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
]);
|
||||
|
||||
expect(mockGetLinkPreviewFn.mock.calls.length).toBe(1);
|
||||
|
||||
await sleep(5 * 1000); // 度过窗口期
|
||||
|
||||
await Promise.all([
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
fetchLinkPreview('foo'),
|
||||
]);
|
||||
|
||||
expect(mockGetLinkPreviewFn.mock.calls.length).toBe(2);
|
||||
},
|
||||
10 * 1000
|
||||
);
|
||||
});
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) =>
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, ms)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { getLinkPreview } from 'link-preview-js';
|
||||
|
||||
/**
|
||||
* 请求管理
|
||||
*/
|
||||
const cacheRequestList: Record<string, Promise<any>> = {};
|
||||
|
||||
/**
|
||||
* 获取网页元数据信息
|
||||
* @param url 网址
|
||||
* @returns
|
||||
*/
|
||||
export async function fetchLinkPreview(url: string): Promise<any> {
|
||||
if (cacheRequestList[url]) {
|
||||
// 如果有正在请求的信息
|
||||
return Promise.resolve(cacheRequestList[url]);
|
||||
}
|
||||
|
||||
const promise = getLinkPreview(url);
|
||||
cacheRequestList[url] = promise;
|
||||
|
||||
return Promise.resolve(promise).finally(() => {
|
||||
setTimeout(() => {
|
||||
delete cacheRequestList[url];
|
||||
}, 2 * 1000); // 窗口期, 请求完毕后2s内依旧会复用原来的接口
|
||||
});
|
||||
|
||||
// return promise;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import got from 'got';
|
||||
import _ from 'lodash';
|
||||
|
||||
/**
|
||||
* 获取特定页面的信息
|
||||
*/
|
||||
|
||||
// <iframe src="//player.bilibili.com/player.html?aid=938355060&bvid=BV1bT4y1a7RH&cid=577883291&page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>
|
||||
|
||||
const specialWebsiteMetaFetchers = [
|
||||
{
|
||||
// bilibili
|
||||
match: (url: string) => url.startsWith('https://www.bilibili.com/video/BV'),
|
||||
overwrite: async (url: string) => {
|
||||
// from https://github.com/simon300000/bili-api/blob/master/src/api/api.bilibili.com.js
|
||||
const bvid = _.last(url.split('?')[0].split('/').filter(Boolean));
|
||||
|
||||
const { data } = await got(
|
||||
`https://api.bilibili.com/x/web-interface/view?bvid=${bvid}`
|
||||
).json<any>();
|
||||
|
||||
const aid = _.get(data, 'aid');
|
||||
const cid = _.get(data, 'cid');
|
||||
if (aid && bvid && cid) {
|
||||
return {
|
||||
videos: [
|
||||
`https://player.bilibili.com/player.html?aid=${aid}&bvid=${bvid}&cid=${cid}&page=1&autoplay=0`,
|
||||
],
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* 获取更多的信息
|
||||
* @param url 请求数据的地址
|
||||
*/
|
||||
export async function fetchSpecialWebsiteMeta(url: string) {
|
||||
const matched = specialWebsiteMetaFetchers.find((f) => f.match(url));
|
||||
|
||||
if (matched) {
|
||||
const overwrite = await matched.overwrite(url);
|
||||
|
||||
return overwrite ?? {};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
Reference in New Issue
Block a user