我正在参与掘金会员专属活动-源码共读第一期,点击参与
前言
今天在翻阅源码课程的时候注意到一个我比较感兴趣的东西,open 打开浏览器。于是我便开始学习这个东西的源码。
open
在 open 的源码部分的 readme 文档里,除了介绍了对它的使用方法以外,我们也可以看到对它的一些描述。
使用方法我们就不看了,我们直接进入阅读源码部分,来了解它的原理和源码。
源码笔记
首先我们根据若川大佬的指引先来写一段测试 Demo,如下所示。
我们打开 index.js 文件,代码是比较多的,我们看关键代码即可。
open
这个是一个 open 打开函数。
const open = (target, options) => {
if (typeof target !== 'string') {
throw new TypeError('Expected a `target`');
}
return baseOpen({
...options,
target
});
};
openApp
这个是和上次差不多的一个打开函数,只不过这个从字面上理解是打开 App。
const openApp = (name, options) => {
if (typeof name !== 'string') {
throw new TypeError('Expected a `name`');
}
const {arguments: appArguments = []} = options || {};
if (appArguments !== undefined && appArguments !== null && !Array.isArray(appArguments)) {
throw new TypeError('Expected `appArguments` as Array type');
}
return baseOpen({
...options,
app: {
name,
arguments: appArguments
}
});
};
baseOpen
很容易看出,函数内部的逻辑并不复杂,但是这两个函数内都调用了 baseOpen 函数,我们来看看 baseOpen 函数是怎么写的。
const baseOpen = async options => {
options = {
wait: false,
background: false,
newInstance: false,
allowNonzeroExitCode: false,
...options
};
......
let command;
const cliArguments = [];
const childProcessOptions = {};
......
由于代码比较多,所以省略了一部分代码。从代码层面可以看出,对于不同的系统它使用 child_process 模块中的 spawn 方法。对于函数内部,我们还可以注意到使用了 pTryEach 方法。
pTryEach
这个函数的内部逻辑也不难,就是进行了一个简单的遍历。
const pTryEach = async (array, mapper) => {
let latestError;
for (const item of array) {
try {
return await mapper(item);
} catch (error) {
latestError = error;
}
}
throw latestError;
};
总结
这次的源码学习起来还是有点吃力的,还是有很多方面没有掌握弄懂。不过没关系,还会继续学习这一部分的,以上就是我学习中的记录及笔记。
最后用若川大佬的一句话来总结一下 open:针对不同的系统,使用Node.js的子进程 child_process 模块的spawn方法,调用系统的命令打开浏览器。