Gowhich

Durban's Blog

试题是这样的


You have a list with website URLs with some mistakes — capital letters. Print the number of the list elements, fix the mistakes in each element of this list, make a map with the domains as key and the length of the respective URLs as value. Try to do it within the body of a proper scope function.
Note: Don’t print the whole map, only return it.

Sample Input 1:

1
htTpS://hypeRskIll.org HTTPS://www.jetbrains.com https://github.com

Sample Output 1:

1
2
3
{https://hyperskill.org=22, https://www.jetbrains.com=25, https://github.com=18}

Write a program in Kotlin

1
2
3
fun filterAndMatch() : Map<String, Int>{
//write your code here
}

在【腾讯元宝】使用Hunyuan

腾讯元宝

在【豆包】直接使用AI编程

豆包

在【腾讯元宝】使用DeepSeek

腾讯元宝

最终选择

从答案的简洁上我会选择豆包给的答案,【腾讯元宝】Hunyuan模型给的答案,我个人不会采用,有点罗嗦,而且不符合出题的意思,【腾讯元宝】DeepSeek模型给的答案,比较周全,比如多了一个filter

最主要的问题【腾讯元宝】Hunyuan模型似乎没有理解题目的意思

从题目看第一步需要获取输入的内容,Hunyuan就创建了一个变量,这一点看出并没有理解题目的意思

移动端开发或者是浏览器都会遇到这个问题,尤其是最近几年ES6语法比较流行,很多浏览器也都支持了,但是很多用户并没有将浏览器更新到最新版本,这样就会遇到一个显示的问题,不支持ES6语法的不支持,如果是在开发中使用的打包工具的话,如webpack等,也许这个问题还要解决,在打包过程中使用babel工具,便可以自动的将需要的es6语法转译为es5语法,从而完美的解决兼容性,但是往往我们在开发的过程中,总是避免不了需要进行简单的页面开发,那么就没必要进行复杂的工具配置,比如webpack等的配置,因为开发前期还是比较费时间的。当然也有很多的工具都是现成的,只需要npm install一下,然后执行对应的命令就可以,连webpack都不需要进行配置,那么这个时候是不是还要进行安装,如果网络好的话,或许能立刻开工进行开发,但是网络不好估计半天的时间就没有了。所以我们看下如何在浏览器下进行兼容呢

有了这个库,也许会解决这个问题,至少我是这么干的,也许适合你,能够帮你解决es6中promise的问题

下面是ES6的项目地址 https://github.com/stefanpenner/es6-promise

Downloads

es6-promise 27.86 KB (7.33 KB gzipped) es6-promise-auto 27.78 KB (7.3 KB gzipped) - Automatically provides/replaces Promise if missing or broken. es6-promise-min 6.17 KB (2.4 KB gzipped) es6-promise-auto-min 6.19 KB (2.4 KB gzipped) - Minified version of es6-promise-auto above.

CDN

1
2
3
4
5
6
7
<!-- Automatically provides/replaces `Promise` if missing or broken. -->
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>

<!-- Minified version of `es6-promise-auto` below. -->
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js"></script>

说下实际情况下如何使用

将下面的代码放在所有js引入入口的最前面(或者按需来操作也行)

1
2
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js"></script>

然后下面这种带有then语法的就能解决了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
axios.post('/api/activity/qrj/buy', {
id: gift.img_id || gift.id || 0,
user_star_autokid: autokid,
}).then(function (response) {
// ...
}).catch(function (error) {
// ...
});
html2canvas(document.querySelector("#canvas-container"), {
dpi: window.devicePixelRatio,
useCORS: true,
width: window.document.body.offsetWidth, //获取当前网页的宽度
height: offsetHeight, //获取当前网页的高度
windowWidth: document.body.scrollWidth, //获取X方向滚动条内容
windowHeight: windowHeight, //获取Y方向滚动条内容
x: 0,
y: offset,
}).then(function(canvas){
// var urlBase64Data = canvas.toDataURL('image/webp', 0.8);
// ...
}).catch(function(e){
// ...
});

html2canvas兼容ES6的使用说明详见:https://www.javascripting.com/view/html2canvas

Polyfill(也许你需要)

我是没有找到具体的项目下载地址

唯一我找到能在浏览器中直接使用的源文件是在这里,版本可能会过期

你可以通过下面的安装命令获取到

1
npm install --save @babel/polyfill

然后在node_modules目录下面babel/polyfill/dist目录下面,即node_modules/@babel/polyfill/dist,一般会有两个文件

1
2
polyfill.js
polyfill.min.js

选择自己需要的就可以了。

iframe无边框示例,网上很多帖子其实只告诉了我们一部分

1
<iframe src="https://gowhich.com" id='other_ad' width="100%" height="568" scrolling="yes" frameborder="no" border="0" marginwidth="0" marginheight="0" allowtransparency="yes" style="border:0"></iframe>

如果单单只是这一部分的话,是不起作用的(在某些情况下)

其实主要原因是部分浏览器默认的margin和padding并没有设置为0,实际上还需要加一些css style

1
2
3
4
5
6
7
8
9
10
<style>
* {
margin:0;
padding:0;
}

html {
font-size: 3.125vw;
}
</style>

完整的示例代码如下

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
26
<!DOCTYPE html>
<html>
<head>
<meta charset=UTF-8>
<meta http-equiv=X-UA-Compatible>
<meta name=format-detection content="telephone=no">
<meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
<link rel="shortcut icon" href="yours">
<title>小游戏</title>
</head>
<style>
* {
margin:0;
padding:0;
}

html {
font-size: 3.125vw;
}
</style>
<body style="background:#270f48">
<div id="app" v-cloak>
<iframe src="https://gowhich.com" id='other_ad' width="100%" height="568" scrolling="yes" frameborder="no" border="0" marginwidth="0" marginheight="0" allowtransparency="yes" style="border:0"></iframe>
</div>
</body>
</html>

背景介绍

使用的是阿里云的服务器,最近报警了,提示我服务器有漏洞,要进行修复升级,然后看了下详情,给出的修复命令如下

1
2
3
yum update libcurl-devel
yum update libcurl
yum update curl

好吧,我能力低,我技术不行,承认自己,于是便执行了下,执行完之后,没有发现任何异常。

但是!我邮箱在不断的收到curl的报错异常,于是我检查代码,添加各种日志,依然没有发现具体是哪里的问题,于是开始猜测访问频次高的接口。

不测不知道一测发现了问题

在PHP中用curl调用的时候第一次是没有问题的,第二次就出现问题了

但是在命令行下面都是正常的

基本报错日志信息如下

错误信息1

1
2
3
4
5
6
7
8
* About to connect() to api.gowhich.com port 443 (#1)
* Trying 10.252.117.104...
* Connected to api.gowhich.com (10.252.117.104) port 443 (#1)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* Unable to initialize NSS database
* Initializing NSS with certpath: none
* Unable to initialize NSS
* Closing connection 1

错误信息2

1
2
3
4
5
6
* Initializing NSS with certpath: none
* NSS error -5978 (PR_NOT_CONNECTED_ERROR)
* Network file descriptor is not connected
* Closing connection 0
int(35)
Network file descriptor is not connected

curl安装完之后的版本

1
curl -V

版本信息如下

1
2
3
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.44 zlib/1.2.7 libidn/1.28 libssh2/1.8.0
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets

通过如下命令访问

1
curl -I -X GET -v https://api.gowhich.com

结果如下

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
26
27
28
29
30
31
32
33
34
35
36
* About to connect() to api.gowhich.com port 443 (#0)
* Trying 10.252.117.104...
* Connected to api.gowhich.com (10.252.117.104) port 443 (#0)
* Initializing NSS with certpath: none
* CAfile: /etc/pki/tls/certs/ca-bundle.crt
CApath: none
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=*.gowhich.com
* start date: 8月 05 00:00:00 2019 GMT
* expire date: 10月 03 12:00:00 2020 GMT
* common name: *.gowhich.com
* issuer: CN=RapidSSL RSA CA 2018,OU=www.digicert.com,O=DigiCert Inc,C=US
> GET / HTTP/1.1
> User-Agent: curl/7.29.0
> Host: api.gowhich.com
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Server: nginx/1.6.3
Server: nginx/1.6.3
< Date: Tue, 18 Feb 2020 08:40:32 GMT
Date: Tue, 18 Feb 2020 08:40:32 GMT
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Content-Length: 11
Content-Length: 11
< Connection: keep-alive
Connection: keep-alive
< ETag: W/"b-+mppjeYkbwpj8ck3uudlJA"
ETag: W/"b-+mppjeYkbwpj8ck3uudlJA"

<
* Excess found in a non pipelined read: excess = 11 url = / (zero-length body)
* Connection #0 to host api.gowhich.com left intact

通过上面的一系列问题,原因就是本机的php调用curl时出现了问题,我猜测时php不兼容nss版本的curl,但是我看过其他服务器使用确实是nss版本的curl,只不过nss的版本不同,

如果你是在命令行下执行php的话

可以通过加变量的方式,这个方法是网上查到的资料(命令如下)

1
export NSS_STRICT_NOFORK=DISABLED

如果要取消的话可以如下操作

1
export NSS_STRICT_NOFORK=1

或者

1
unset NSS_STRICT_NOFORK

但是文章上好像说 不建议在生产环境中使用

参考文章链接:https://cohan.dev/php-curl-libcurl-error-on-subsequent-requests/

但是我在webapp中要如何去设置这个参数,我还真不知道了。

最后的解决方案,替换nss版本的curl,改换成openssl版本的curl。

我下载的curl版本是 curl-7.27.0.tar.gz

然后下载一个与你php版本一致的包 我的是 php-7.0.6.tar.gz

(非root用户,但是有root权限的命令如下,如果是root的话,会有一些不同)

下载后分别解压下

1
tar -zxvf ***.tar.gz

先安装下curl

1
2
3
4
cd curl-7.27.0

./configure --without-nss --with-ssl
make && sudo make install

再安装php的curl

1
2
3
4
cd php-7.0.6/ext/curl
phpize
./configure --with-curl=/usr/local
make && sudo make install

安装完之后重启php-fpm

1
/etc/init.d/php-fpm restart

结果修复了。

ssl证书获取

免费的渠道 https://certbot.eff.org/

也可以去云平台获取 比如阿里云、腾讯云也有免费的

先说下 ssl/dhparam.pem 这个文件如何获取

如何生成 dhparam.pem 文件

在命令行执行任一方法:

方法1: 很慢

1
openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

方法2: 较快 - 与方法1无明显区别. 2048位也足够用, 4096更强

1
openssl dhparam -dsaparam -out /etc/nginx/ssl/dhparam.pem 4096

参考 https://gist.github.com/fotock/9cf9afc2fd0f813828992ebc4fdaad6f

采用七牛的SDK方式上传(qiniu sdk文件可以去官网示例页面下载,放在github上的文件需要自己下载后打包的,很麻烦)

首先看下公用的上传函数

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
function uploadWithSDK (file, token, putExtra, config, domain) {
var self = this;

var finishedAttr = [];

var compareChunks = [];

var observable;

if (file) {
// var key = file.name;
var key = 'activity/' + (new Date().valueOf()) + '/' + self.uploadKey;
putExtra.params["x:name"] = key.split(".")[0];

// 设置next,error,complete对应的操作,分别处理相应的进度信息,错误信息,以及完成后的操作
var error = function (err) {
console.log('err = ', err);
self.uploading = false;
};

var complete = function (res) {
console.log('res = ', res);
self.uploading = false;
self.uploaded = true;
var url = self.domain + '/' + res.key;
console.log(url);
self.videoUrl = url
};

var next = function (response) {
var chunks = response.chunks || [];
var total = response.total;
console.log('total = ', total);
console.log('chunks = ', chunks);
self.uploadPercent = (total.percent + '').substr(0, 5) + '%';
};

var subObject = {
next: next,
error: error,
complete: complete
};

var subscription;

// 调用sdk上传接口获得相应的observable,控制上传和暂停
observable = qiniu.upload(file, key, token, putExtra, config);

subscription = observable.subscribe(subObject);

// subscription.unsubscribe();
}
}

调用上传视频函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function uploadVideo(event) {
var file = event.target.files[0];
// this.uploading = true;

console.log(file);
console.log(file.size);

var config = {
useCdnDomain: true,
disableStatisticsReport: false,
retryCount: 6,
region: qiniu.region.z0
};

var putExtra = {
fname: "",
params: {},
mimeType: null
};

uploadWithSDK(file, this.uploadToken, putExtra, config, this.domain);
}

触发file的click事件

1
2
3
function upload() {
this.$refs.fileElem.dispatchEvent(new MouseEvent('click'));
}

从上面代码可以看出, 代码适用于vuejs中,但是触发click的话,只要是js代码都能实现

vuejs中视频上传相关变量初始化

1
2
3
4
5
6
7
8
9
10
data: {
uploadToken: '',
domain: '',
uploadKey: '',
randomKey: '',
uploading: false,
uploaded: false,
videoUrl: '',
uploadPercent: '',
}

vuejs中上传视频隐藏表单的HTML

1
2
3
4
5
6
<!-- 上传图片的隐藏元素 -->
<div style="display:none">
<form id="fileElem1">
<input ref=fileElem type="file" class="file" accept="video/*" name="img" @change="uploadVideo($event)" style="display: none">
</form>
</div>

vuejs中上传视频按钮部分

1
<span @click='upload' style="">上传视频</span>

这里七牛的sdk请去官网下载

想不通直接打包一个不挺好的嘛,自己下载下来非常麻烦。(实例地址 http://jssdk-v2.demo.qiniu.io/)

git-flow 工作流程

当在团队开发中使用版本控制系统时,商定一个统一的工作流程是至关重要的。Git 的确可以在各个方面做很多事情,然而,如果在你的团队中还没有能形成一个特定有效的工作流程,那么混乱就将是不可避免的。

基本上你可以定义一个完全适合你自己项目的工作流程,或者使用一个别人定义好的。

什么是git-flow

一旦安装 git-flow,你将会拥有一些扩展命令。这些命令会在一个预定义的顺序下自动执行多个操作。是的,这就是我们的工作流程!

git-flow 并不是要替代 Git,它仅仅是非常聪明有效地把标准的 Git 命令用脚本组合了起来。

严格来讲,你并不需要安装什么特别的东西就可以使用 git-flow 工作流程。你只需要了解,哪些工作流程是由哪些单独的任务所组成的,并且附带上正确的参数,以及在一个正确的顺序下简单执行那些对应的 Git 命令就可以了。当然,如果你使用 git-flow 脚本就会更加方便了,你就不需要把这些命令和顺序都记在脑子里

安装git-flow

近些年来出现了很多不同的安装方法。在本章节中我们会使用当前最流行的一种: AVH Edition

要了解安装 git-flow 细节,请阅读下面这个文档 official documentation

在项目中设置 git-flow

当你想把你的项目 “切换” 到 git-flow 上后,Git 还是可以像往常一样工作的。这完全是取决于你在仓库上使用特殊的 git-flow 命令或是普通的 Git 命令。换句话说,git-flow 它不会以任何一种戏剧性的方式来改变你的仓库。

话虽如此,git-flow 却存在一些限制。让我们开始在一个新的项目上初始化它吧,之后我们就会有所发现:

1
2
3
4
5
6
7
8
9
$ git flow init
Initialized empty Git repository in /Users/xxx/xxx-website/.git/
Branch name for production releases: [master]
Branch name for "next release" development: [develop]

How to name your supporting branch prefixes?
Feature branches? [feature/]
Release branches? [release/]
Hotfix branches? [hotfix/]

当在项目的根目录执行 “git flow init” 命令时(它是否已经包括了一个 Git 仓库并不重要),一个交互式安装助手将引导您完成这个初始化操作。听起来有点炫,但实际上它只是在你的分支上配置了一些命名规则。 尽管如此,这个安装助手还是允许你使用自己喜欢的名字。我强烈建议你使用默认的命名机制,并且一步一步地确定下去。

分支的模式

git-flow 模式会预设两个主分支在仓库中:

  • master 只能用来包括产品代码。你不能直接工作在这个 master 分支上,而是在其他指定的,独立的特性分支中(这方面我们会马上谈到)。不直接提交改动到 master 分支上也是很多工作流程的一个共同的规则。
  • develop 是你进行任何新的开发的基础分支。当你开始一个新的功能分支时,它将是_开发_的基础。另外,该分支也汇集所有已经完成的功能,并等待被整合到 master 分支中。

master

这两个分支被称作为 长期分支。它们会存活在项目的整个生命周期中。而其他的分支,例如针对功能的分支,针对发行的分支,仅仅只是临时存在的。它们是根据需要来创建的,当它们完成了自己的任务之后就会被删除掉。

长期分支

让我们开始探索一些在现实应用中可能遇到的案例吧!

功能开发

对于一个开发人员来说,最平常的工作可能就是功能的开发。这就是为什么 git-flow 定义了很多对于功能开发的工作流程,从而来帮助你有组织地完成它。

开始新功能

让我们开始开发一个新功能 “rss-feed”:

1
2
3
4
5
6
$ git flow feature start rss-feed
Switched to a new branch 'feature/rss-feed'

Summary of actions:
- A new branch 'feature/rss-feed' was created, based on 'develop'
- You are now on branch 'feature/rss-feed'

正如上面这个新功能一样,git-flow 会创建一个名为 “feature/rss-feed” 的分支(这个 “feature/” 前缀 是一个可配置的选项设置)。你已经知道了,在你做新功能开发时使用一个独立的分支是版本控制中最重要的规则之一。 git-flow 也会直接签出这个新的分支,这样你就可以直接进行工作了。

完成一个功能

经过一段时间艰苦地工作和一系列的聪明提交,我们的新功能终于完成了:

1
2
3
4
5
6
7
8
$ git flow feature finish rss-feed
Switched to branch 'develop'
Updating 6bcf266..41748ad
Fast-forward
feed.xml | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 feed.xml
Deleted branch feature/rss-feed (was 41748ad).

最重要的是,这个 “feature finish” 命令会把我们的工作整合到主 “develop” 分支中去。在这里它需要等待:

  • 一个在更广泛的 “开发” 背景下的全面测试。
  • 稍后和所有积攒在 “develop” 分支中的其它功能一起进行发布。 之后,git-flow 也会进行清理操作。它会删除这个当下已经完成的功能分支,并且换到 “develop” 分支。

管理 releases

Release 管理是版本控制处理中的另外一个非常重要的话题。让我们来看看如何利用 git-flow 创建和发布 release。

创建 release

当你认为现在在 “develop” 分支的代码已经是一个成熟的 release 版本时,这意味着:第一,它包括所有新的功能和必要的修复;第二,它已经被彻底的测试过了。如果上述两点都满足,那就是时候开始生成一个新的 release 了:

1
2
$ git flow release start 1.1.5
Switched to a new branch 'release/1.1.5'

请注意,release 分支是使用版本号命名的。这是一个明智的选择,这个命名方案还有一个很好的附带功能,那就是当我们完成了release 后,git-flow 会适当地_自动_去标记那些 release 提交。

有了一个 release 分支,再完成针对 release 版本号的最后准备工作(如果项目里的某些文件需要记录版本号),并且进行最后的编辑。

完成 release

现在是时候按下那个危险的红色按钮来完成我们的release了:

1
git flow release finish 1.1.5

这个命令会完成如下一系列的操作:

  • 首先,git-flow 会拉取远程仓库,以确保目前是最新的版本。
  • 然后,release 的内容会被合并到 “master” 和 “develop” 两个分支中去,这样不仅产品代码为最新的版本,而且新的功能分支也将基于最新代码。
  • 为便于识别和做历史参考,release 提交会被标记上这个 release 的名字(在我们的例子里是 “1.1.5”)。
  • 清理操作,版本分支会被删除,并且回到 “develop”。 从 Git 的角度来看,release 版本现在已经完成。依据你的设置,对 “master” 的提交可能已经触发了你所定义的部署流程,或者你可以通过手动部署,来让你的软件产品进入你的用户手中。

hotfix

很多时候,仅仅在几个小时或几天之后,当对 release 版本作做全面测试时,可能就会发现一些小错误。 在这种情况下,git-flow 提供一个特定的 “hotfix” 工作流程(因为在这里不管使用 “功能” 分支流程,还是 “release” 分支流程都是不恰当的)。

创建 Hotfixes

1
$ git flow hotfix start missing-link

这个命令会创建一个名为 “hotfix/missing-link” 的分支。因为这是对产品代码进行修复,所以这个 hotfix 分支是基于 “master” 分支。 这也是和 release 分支最明显的区别,release 分支都是基于 “develop” 分支的。因为你不应该在一个还不完全稳定的开发分支上对产品代码进行地修复。

就像 release 一样,修复这个错误当然也会直接影响到项目的版本号!

完成 Hotfixes

在把我们的修复提交到 hotfix 分支之后,就该去完成它了:

1
$ git flow hotfix finish missing-link

这个过程非常类似于发布一个 release 版本:

完成的改动会被合并到 “master” 中,同样也会合并到 “develop” 分支中,这样就可以确保这个错误不会再次出现在下一个 release 中。 这个 hotfix 程序将被标记起来以便于参考。 这个 hotfix 分支将被删除,然后切换到 “develop” 分支上去。 还是和产生 release 的流程一样,现在需要编译和部署你的产品(如果这些操作不是自动被触发的话)。

原文地址:https://www.git-tower.com/learn/git/ebook/cn/command-line/advanced-topics/git-flow

swift代码中时长会遇到codable的用法

但是不太理解其中的含义,也不太理解如何使用

于是google后发现了一篇比较好的文章,点这里

从代码中,或者实例中我们会遇到类似的使用方法

1
struct Landmark: Hashable, Codable

继承了Codable的话,就需要实现其中的协议方法

It’s pretty easy, just use String or Int raw values which are implicitly assigned.

看几个例子,引用了上面提到的文章中的例子

1
2
3
enum PostType: Int, Codable {
case image, blob
}

这样用之后

image的值为0

blob的值为1

1
2
3
enum PostType: String, Codable {
case image, blob
}

这样用之后

image的值为字符串 “image”

blob的值为字符串 “blob”

下面看下这个特殊的特性如何使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enum PostType : Int, Codable {
case count = 4
}

struct Post : Codable {
var type : PostType
}

let jsonString = "{\"type\": 4}"

let jsonData = Data(jsonString.utf8)

do {
let decoded = try JSONDecoder().decode(Post.self, from: jsonData)
print("decoded:", decoded.type)
} catch {
print(error)
}

如果这个例子能够看懂的话,那么下下面这个例子也是很容易理解的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct Landmark: Hashable, Codable {
var id: Int
var name: String
fileprivate var imageName: String
fileprivate var coordinates: Coordinates

var state: String
var park: String
var categroy: Category

var locationCoordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(latitude: coordinates.latitude, longitude: coordinates.longitude)
}

enum Category: String, Hashable {
case featured = "Featured"
case lakes = "Lakes"
case rivers = "Rivers"
}
}

运行后,会遇到如下错误

报错信息如下

1
Type 'Landmark' does not conform to protocol 'Decodable'

完整的,无问题的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct Landmark: Hashable, Codable {
var id: Int
var name: String
fileprivate var imageName: String
fileprivate var coordinates: Coordinates

var state: String
var park: String
var categroy: Category

var locationCoordinate: CLLocationCoordinate2D {
CLLocationCoordinate2D(latitude: coordinates.latitude, longitude: coordinates.longitude)
}

enum Category: String, Hashable, Codable {
case featured = "Featured"
case lakes = "Lakes"
case rivers = "Rivers"
}
}

从上面的例子中可以看出,Codable使用在struct和enum组合的使用方式中。

event - 错误事件和仅处理事件一次

当使用 eventEmitter.on() 注册监听器时,监听器会在每次触发命名事件时被调用。

1
2
3
4
5
6
7
8
9
10
const EventEmitter = require("events");

const emitter = new EventEmitter();

emitter.on("event", function () {
console.log("event emitter");
});

emitter.emit("event");
emitter.emit("event");

运行后得到的结果如下

1
2
3
$ node main.js
event emitter
event emitter

使用 eventEmitter.once() 可以注册最多可调用一次的监听器。 当事件被触发时,监听器会被注销,然后再调用。

1
2
3
4
5
6
7
8
9
10
const EventEmitter = require("events");

const emitter = new EventEmitter();

emitter.once("event", function () {
console.log("event emitter");
});

emitter.emit("event");
emitter.emit("event");

运行后得到的结果如下

1
2
$ node main.js
event emitter

(错误事件)Error events

1
2
3
4
5
const EventEmitter = require("events");

const emitter = new EventEmitter();

emitter.emit("error", new Error("i am a error"));

运行结果如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ node main.js
events.js:174
throw er; // Unhandled 'error' event
^

Error: i am a error
at Object.<anonymous> (/Users/durban/nodejs/main.js:45:23)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)
Emitted 'error' event at:
at Object.<anonymous> (/Users/durban/nodejs/main.js:45:9)
at Module._compile (internal/modules/cjs/loader.js:778:30)
[... lines matching original stack trace ...]
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

再看下面实例

1
2
3
4
5
6
7
8
9
10
const EventEmitter = require("events");

const emitter = new EventEmitter();

emitter.on("error", function (error) {
console.log("i am catch a error");
console.log(error);
});

emitter.emit("error", new Error("i am a error"));

运行后结果如下

1
2
3
4
5
6
7
8
9
10
11
12
$ node main.js
i am catch a error
Error: i am a error
at Object.<anonymous> (/Users/durban/nodejs/main.js:77:23)
at Module._compile (internal/modules/cjs/loader.js:778:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
at startup (internal/bootstrap/node.js:283:19)
at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)

event(事件)的简单使用记录再次

Party popper The Elephpant is going on further adventures!

PHP 8 is in feature freeze, and beta1 is released. Get on with yer testing! Bugs to https://bugs.php.net

There are also new security releases stable PHP versions: 7.2.33, 7.3.21 and 7.4.9. Get upgrading!

这里是php的todo列表 https://wiki.php.net/todo/php80

0%