0%

2021-12-13 使用 Promise.any 选择最快的镜像

2021-12-13 使用 Promise.any 选择最快的镜像

之前写的 cmyr-template-cli/草梅项目模板创建器 是直接从 GitHub 下载模板的,但由于众所周知的原因,从 GitHub 上下载模板总是断断续续的,最近就失败了好几次,忍无可忍了所以决定加个镜像源。

一番寻找之下确定了镜像源如下(包含原版 GitHub)

1
2
3
4
5
6
7
const REMOTES = [
'https://github.com',
'https://hub.fastgit.org',
'https://gitclone.com',
'https://github.com.cnpmjs.org',
]

然后是使用 Promise.any 函数来选择哪个镜像源是最快的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 从 github 和镜像中选择最快的源
* @param repository 源 owner/name, 例如 CaoMeiYouRen/rollup-template
*/
export async function getFastGitRepo(repository: string) {
const loading = ora(`正在选择镜像源 - ${repository}`)
loading.start()
try {
const fast = await Promise.any(REMOTES.map((remote) => {
const url = `${remote}/${repository}/archive/refs/heads/master.zip`
return axios({ // 直接利用 axios 发个 HEAD 请求来测试速度, HEAD 请求只会返回响应头,不会返回 body ,所以速度要快一些
url,
method: 'HEAD',
timeout: 15 * 1000,
})
}))
return `direct:${fast.config.url}`
} catch (error) {
console.error(error)
process.exit(1)
} finally {
loading.stop()
}
}

Promise.any 函数是有一个子实例成功就算成功,全部子实例失败才算失败,所以只要第一个镜像源访问成功了就会直接结束,也就不用浪费时间等最后一个返回了。

不过在实际运行的时候发生了 Promise.any not a function 的问题,检查了下发现是我的 Node.js 版本不支持这个函数,所以找了个 shim。

1
2
3
4
5
import any from 'promise.any'

if (!Promise.any) {
Promise.any = any
}

成功执行!

本文作者:草梅友仁
本文地址: https://blog.cmyr.ltd/archives/a3b3ded7.html
版权声明:转载请注明出处!

坚持原创技术分享,您的支持将鼓励我继续创作!