Giter Site home page Giter Site logo

blog's People

Contributors

for2me avatar forzys avatar

Stargazers

 avatar

Watchers

 avatar

blog's Issues

关于Promise

  • 什么是Promise
Promise 是 ES6 异步编程的一种解决方案 (目前最先进的解决方案是 async 和 await 的搭配(ES8),
但是它们是基于 promise 的),从语法上讲,Promise 是一个对象或者说是构造函数,
用来封装异步操作并可以获取其成功或失败的结果
  • 为什么要使用 Promise
最重要也是最主要的一个场景就是ajax 和axios 请求。
通俗来说,由于网速的不同,可能你得到返回值的时间也是不同的,
但是我们下一步要执行的代码依赖于上一次请求返回值,
这个时候我们就需要等待,结果出来了之后才知道怎么样继续下去。 
  • Promise 的好处
防止出现回调地狱;
提高代码的可读性;
像同步操作那样去执行异步操作
  • Promise 的三种状态
1.pending: 等待中,或者进行中,表示还没有得到结果
2.resolved(Fulfilled): 已经完成,表示得到了我们想要的结果,可以继续往下执行
3.rejected: 也表示得到结果,但是由于结果并非我们所愿,因此拒绝执行
  • Promise总结
1. promise 其实就是一个对象或者说是构造函数
2. promise 的出现(es6) 就是解决异步编程和回掉地狱等问题,
async 和 await 的出现(ES8)就是基于 promise 的一种解决异步编程的终极解决方案(简化代码等等)
3. 在前端中,ajax 和 axios 都会用到异步编程,axios 更是基于 promise 的,
所以一定要掌握promise 以及用 async 和 await 搭配 promise 的使用
  • Promise 手写实现
const PEDDING = 'pedding';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
	#state = PEDDING
	#result = undefined
	#handlers = []

	constructor(executor){
		const resolve = (data)=>{
			this.#changeState(FULFILLED, data)
		}
		const reject = (reason)=>{
			this.#changeState(REJECTED, reason)
		}
	
		try{
			executor(resolve, reject)
		}catch(error){
			reject(error)
		}
	}
	
	#changeState(status, result){
		if(this.#state !== PEDDING) return
		this.#state = status
		this.#result = result
		this.#run()
	}
	
	#isPromise(value){
		if(value === null){
			return false
		}
		const typeRight = typeof value === 'object' || typeof value === 'function'
		if(typeRight && typeof value.then === 'function'){
			return true
		}
		return false
	}
	 
	#runFn(callback, resolve, reject){
		queueMicrotask(()=>{
			if(typeof callback !== 'function'){
				const settled = this.#state === FULFILLED ? resolve : reject
				settled(this.#result) 
				return 
			}
		
			try{
				const data = callback(this.#result)
				if(this.#isPromise(data)){
					data.then(resolve, reject)
				}else{
					resolve(data) 
				} 
			}catch(error){
				reject(error)
			}
		})
	}
	
	#run(){
		if(this.#state === PEDDING) return
		while(this.#handlers.length > 0){
			const { 
				onFulFilled, 
				onRejected, 
				resolve,
				reject,
			} = this.#handlers.shift()
			
			if(this.#state === FULFILLED){
				this.#runFn(onFulFilled, resolve, reject)
			}else{
				this.#runFn(onRejected, resolve, reject)
			} 
		}
	}
	
	then(onFulFilled, onRejected){
		return new MyPromise((resolve, reject)=>{
				this.#handlers.push({
					onFulFilled,
					onRejected, 
					resolve,
					reject,
				})
				this.#run()
		}) 
	}
}

Git cherry-pick 分支出现冲突的解决方式

场景: master分支 cherry-pick testing分支的提交内容(commit)时发现有大量冲突

原因: 之前master分支cherry-pick过testing分支的内容 且解决了冲突之后push到master

解决方案:

如果简单少量的冲突可以直接解决冲突后提交

  • git diff testing
  • 解决冲突
  • git commit
  • git push

如果存在大量未提交内容同时希望保留testing的提交记录

  • 找一个存在冲突之前的 commit
  • git checkout commit id src/ common/ (变化内容文件夹
  • git commit -m
  • git diff master..commit id (比较当前与commit id 的内容是否仍有不同)
  • git cherry-pick commit id..new commit id
    (从checkout的commit id一直pick到最新的提交)
  • git push

优点:保留了提交修改的原始记录
缺点:master会出现两条cherry-pick的记录 (之前pick过一次的现在会重新pick一次)


可能需要用到的其他Git命令

    git log --author=username  // 筛选用户提交记录
    git log --grep=keywords    // 筛选关键词提交记录
    git log --pretty=format:"%h %an %cd %s" --date=short  // 美化/格式化 提交记录
    git master2 rebase   // (master2:需要rebase 的分支名) rebase master2 分支

常用Git命令记忆

    git add .  // 暂存本地修改
    git commit -m 'msg'   // 提交本地修改到本地版本库
    git push  // 推送修改到对应的远程分支
    git push origin HEAD:remote_branch  // 推送到自定义远程分支 (远程分支不存在会新建)
    git checkout -b local_branch origin/remote_branch   // 新建远程分支对应的本地分支
    git checkout local_branch  // 切换本地分支
    git branch [-a]  // 查看本地分支 [远程分支]
    git branch -D local_branch // 删除本地分支
    git push origin --delete remote_branch // 删除远程分支 
    git branch --set-upstream-to=origin/remote_branch local_branch // 关联远程分支

虚船触舟有感

虚船触舟有感

庄子·山木 <市南宜僚见鲁侯>

市南子答鲁侯

少君之费,寡君之欲,虽无粮而乃足。君其涉于江而浮于海,望之而不见其崖,愈往而不知其所穷。送君者皆自崖而反,君自此远矣!故有人者累,见有于人者忧。故尧非有人,非见有于人也。吾愿去君之累,除君之忧,而独与道游于大莫之国。方舟而济于河,有虚船来触舟,虽有惼心之人不怒,有一人在其上,则呼张歙之,一呼而不闻,再呼而不闻,于是三呼邪,则必以恶声随之。向也不怒而今也怒,向也虚而今也实。人能虚己以游世,其孰能害之!

虚船触舟的回答很发人深思

乘船来渡河,突然有条空船碰撞过来,即使心地最偏狭、性子最火急的人也不会发怒;倘若有一个人在那条船上,那就会人人大声呼喊喝斥来船后退;呼喊一次没有回应,呼喊第二次也没有回应,于是喊第三次,那就必定会骂声不绝。刚才不发脾气而现在发起怒来,那是因为刚才船是空的而今却有人在船上。一个人倘能听任外物、处世无心而自由自在地遨游于世,谁能够伤害他!

很有意思的是让人生气的原因不是船被撞而是船上是否有人。
很多时候我们并不是对事不对人,很多脾气也一开始就带入了自己的价值观世界观。
一旦对方的想法行为与自己期待的不一致,脾气立马就上来。 (撞船)
被踩一脚让自己很生气,可被小猫踩了一脚呢?

人能虚己以游世,其孰能害之!
很多时候,我们都应该把别人看成一个"空船"


Flex 布局的一些总结

Flex 布局的一些总结

不定个数子元素, 每行N个依次排列

.parent {
    display: flex;
    flex-wrap: wrap; 
}

.child{
    flex: 0 0 calc(33.33% - 16px);  /**(例如 N = 3) 100% / N - 间距  */ 
    margin: 8px;
}

不定个数子元素, 每行N个依次排列 且最后一个子元素靠右排列

.parent {
    display: flex;
    flex-wrap: wrap; 
}
  
.child{
    flex: 0 0 calc(33.33% - 16px);  /**(例如 N = 3) 100% / N - 间距  */ 
    margin: 8px;
}
.child:last-child{
    margin-left: auto;  /** 那个方向的margin auto 就 排斥那个方向 */ 
}

不定个数子元素, 每行N个依次排列 且最后一个子元素居中排列

.parent {
    display: flex;
    flex-wrap: wrap; 
}
  
.child{
    flex: 0 0 calc(33.33% - 16px);  /**(例如 N = 3) 100% / N - 间距  */ 
    margin: 8px;
}
.child:last-child{
    margin: 0 auto;  /** 一般判断最后剩一个元素使用  如果剩多个元素前面的会正常排 最后一个会在剩余空间居中 */ 
}

总结 Rollup and uglify 使用

简介:

rollup是一款小巧的javascript模块打包工具,通过rollup打包后的代码,体积较小,而且没有冗余的代码
rollup提供了五种选项:

  1. AMD: 浏览器端的模块规范, 可通过 RequireJS 可加载
  2. CommonJS: Node 默认的模块规范, 可通过 Webpack 加载
  3. ESM: ES2015 Module 规范, 可用 Webpack, Rollup 加载
  4. IIFE: 自执行函数, 可通过 <script> 标签加载
  5. UMD: 兼容 IIFE, AMD, CJS 三种模块规范

使用配置文件 rollup.config.js

export default {
    input: 'src/main.js',
    output: {
        file: 'bundle.js',
        format: 'cjs'
    },
    plugins: [ 
        babel({ exclude: 'node_modules/**' }), 
        uglify(),
    ]
}

执行 rollup -c rollup.config.js 启动配置项;

rollup and uglify 使用记录

  1. 安装
    yarn add rollup --dev 
    npm install uglify-js -g 
  1. 使用
    var cjs = `yarn rollup [input-file] --format cjs --file [output-file]` 
    var esm = `yarn rollup [input-file] --format esm --file [output-file]`
    var umd = `yarn rollup [input-file] --format umd --name [global-name] --file [output-file]`
  1. 配合 uglifyjs
    uglifyjs [input-file] -m -o [output-file]    
  1. 实例
    yarn rollup ./calendar.js --format cjs --file ./temp.js
    uglifyjs ./temp.js -m -o ./calendar.min.js

    yarn rollup ./calendar.js --format umd --name Calendar --file ./temp.js
    uglifyjs ./temp.js -m -o ./calendar.min.js

Custom Markdown

Custom Markdown

发现一个十分小巧的Markdown解析库 但是十分古老 , 不支持Table、对Code的支持也十分不友好,还发现一些bug等等
所以动手添加了需要的一些功能

修改 pagedown 添加table支持 添加删除线 以及代码块等。
适合个人博客及其他简单的Markdown渲染 。
十分小巧 build后只有10k左右 gzip压缩后只有4k大小 没有其他复杂的功能 提供pluginHooks可自定义渲染内容

custom-markdown


update:

添加hook以支持code语法高亮效果

Todo:

接下来继续修改bug 看看在实际项目中使用的效果如何

React Native 打包发布APK

  • 生成一个签名密钥
$ keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
  • 设置 gradle 变量
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****
  1. my-release-key.keystore文件放到项目中的android/app文件夹下
  2. 项目目录/android/gradle.properties(项目配置,只对所在项目有效)。 添加上面的代码
  • 把签名配置加入到项目的 gradle 配置中

    android {
        ...
        defaultConfig { ... }
        signingConfigs {
            release {
                if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) {
                    storeFile file(MYAPP_RELEASE_STORE_FILE)
                    storePassword MYAPP_RELEASE_STORE_PASSWORD
                    keyAlias MYAPP_RELEASE_KEY_ALIAS
                    keyPassword MYAPP_RELEASE_KEY_PASSWORD
                }
            }
        }
        buildTypes {
            release {
                ...
                signingConfig signingConfigs.release
            }
        }
    }
  • 生成发行 APK 包

    $ cd android
    $ ./gradlew assembleRelease

linear-gradient 渐变背景实现过渡效果

background: linear-gradient 渐变背景实现过渡效果

场景: 做渐变色背景切换的时候发现如果直接改变backgroundlinear-gradient值设置的 transition 属性不会生效。

CSS 过渡效果(transition)是一种在元素从一种状态转换到另一种状态时,实现平滑动画过渡的方法。

只有具有中间值的属性才有过渡效果

颜色:color background-color border-color outline-color
位置:background-position left right top botton
长度:
    [1]max-height min-height max-width min-width height width
    [2]border-width margin padding outline-width outline-offset
    [3]font-size line-height text-indent vertical-align  
    [4]border-spacing letter-spacing word-spacing
数字: opacity visibility z-index font-weight zoom
组合: text-shadow transform box-shadow clip
其他: gradient

background-image不支持 CSS3的 transition.
设置 background gradient 实际是作为 background-image 存在 所以不会有过渡效果.
渐变不支持 transition 那要怎么实现渐变背景的过渡效果呢?

网上找了一圈大概有这几种方法:

1. 利用 background-color

    .box{
        background: #f2f3f4 linear-gradient(to right, rgba(225,255,115,0), rgba(225,255,115,.5));
        transition: background-color .3s;
    }
    .box:hover{
       background-color: #a4907c;
    }
  • background-color 作为底色 通过改变 background-color 实现渐变效果

2. 利用 background-position.

    .box{
        background: linear-gradient(to right, #f2f3f4,  #a4907c);
        background-size: 200%;
        transition: background-position .3s;  
    }
    .box:hover {
        background-position: 100% 0;    
    }
  • background-position 定位放大的背景位置实现渐变效果.

3. 利用 伪元素 配合 opacity

  .box { 
      background: linear-gradient(to right, olive, green);
      position: relative;
      z-index: 0;    
  }
  .box::before {
      content: '';
      position: absolute;
      left: 0; top: 0; right: 0; bottom: 0;
      background: linear-gradient(to right, green, purple);
      opacity: 0;    
      transition: opacity .5s;
      z-index: -1;
  }
  .box:hover::before {
      opacity: 1;    
  }
  • 利用伪元素 配合 opacity 实现渐变效果.

4. 利用 CSS houdini

Houdini 是一组底层 API,它们公开了 CSS 引擎的各个部分,从而使开发人员能够通过加入浏览器渲染引擎的样式和布局过程来扩展 CSS。Houdini 是一组 API,它们使开发人员可以直接访问CSS 对象模型 (CSSOM),使开发人员可以编写浏览器可以解析为 CSS 的代码,从而创建新的 CSS 功能,而无需等待它们在浏览器中本地实现。

.box{
  --bg-0:#98eecc;
  --bg-1:#d0f5be;
  background-image: linear-gradient(180deg, var(--bg-1) 0%, var(--bg-2) 100%);
  transition: --bg-1 .5s, --bg-2 .5s;
} 
.box:hover {
    --bg-0:#fbffdc; 
    --bg-1:#a4907c; 
}
if (window.CSS) {
   (window?.CSS as any)?.registerProperty({
          name: '--bg-0',
          syntax: '<color>',
          inherits: false,
          initialValue: 'transparent'
     });
   (window?.CSS as any)?.registerProperty({
        name: '--bg-1',
        syntax: '<color>',
        inherits: false,
        initialValue: 'transparent'
    });
}

注意TypeScript 编译器无法正确地识别 CSS 对象上的 registerProperty 方法 需要使用类型断言 将CSS对象的类型设置为 any. 当前各浏览器对Houdini的支持情况

4.1 【23-08-08更新】

  • 无需JS参与使用@property规则,对CSS变量进行自定义,可将CSS变量定义为过渡属性
@property --bg-0 { 
    syntax: '<color>';
    inherits: false;
    initial-value: transparent;
}
@property --bg-1 { 
    syntax: '<color>';
    inherits: false;
    initial-value: transparent;
}

.box{
  --bg-0:#98eecc;
  --bg-1:#d0f5be;
  background-image: linear-gradient(180deg, var(--bg-1) 0%, var(--bg-2) 100%);
  transition: --bg-1 .5s, --bg-2 .5s;
} 
.box:hover {
    --bg-0:#fbffdc; 
    --bg-1:#a4907c; 
}

其他方式 例如利用动画属性也可以实现

最终效果 直达

关于事件循环(Event Loop)的理解

关于事件循环(Event Loop)的理解

JavaScript Event Loop 是 JavaScript 运行时的一个重要概念,它控制(保证)着 JavaScript 代码的执行顺序。 Event Loop 是一个持续不断循环执行的过程,它会检查 JavaScript 引擎内部的任务队列,如果队列中有任务,就会依次执行这些任务。当队列为空时,Event Loop 就会等待新的任务加入队列。

事件循环主要分为两个阶段:执行栈任务队列。所有同步任务都在主线程上执行,形成一个执行栈执行栈是一个存储函数调用的栈。当 JavaScript 引擎执行函数时,它会将函数放入执行栈中。当函数执行完毕时,它就会从栈中弹出。而任务队列则是一个用来存储待执行任务的队列,它包含了一些由异步操作(例如,定时器、网络请求、事件处理等)产生的任务。当这些异步操作完成后,它们会被添加到任务队列中,等待 JavaScript 引擎执行。

console.log(1); 

setTimeout(()=>{ console.log(2) },1000);

console.log(3); 

很经典也很简单的代码,不难理解上方代码的输出结果依次为 1、3、2,setTimeout()将第二行推迟到1000毫秒之后执行。因为 js 先把执行栈里打印 1 和 3 的语句执行完毕(同步任务),把定时器事件放入任务队列,最后执行。

setTimeout(()=>{console.log(1)}, 0);

console.log(2);

即使将setTimeout的第二个参数设为0,上面代码的执行结果也总是2,1。因为只有在执行完第二行以后,系统才会去执行任务队列中的回调函数。

因此,可以理解 事件循环 就是先将执行栈中的事件执行完成后再执行任务队列中事件 由此不断循环


而随着 ES6 中 Promise 的出现,任务队列被划分为更加细致的微任务队列宏任务队列

总结一下即异步任务分为 宏任务微任务宏任务会进入宏任务队列,而微任务会进入微任务队列微任务要优于宏任务执行

常见的宏任务和微任务

宏任务:script(整体代码)、setTimeout、setInterval、I/O、事件、postMessage、 MessageChannel、setImmediate (Node.js)
微任务:Promise.then、 MutaionObserver、process.nextTick(Node.js)

console.log('1')

setTimeout(function() {
   Promise.resolve().then(() => {
     console.log('2')
   })
   console.log('3')
}, 0)

new Promise(resolve => {
   console.log('4')
   resolve()
   setTimeout(() => console.log('5'), 0)
}).then(function() {
   console.log('6')
})

console.log('7')

根据理解可以解上面的题:

1. 先执行执行栈中的同步任务

  • 遇到 console.log('1') 直接执行打印 1
  • 遇到 setTimeout 将回调函数放入宏任务队列
  • 进入 Promise(回调函数立即执行) 遇到 console.log('4') 直接执行打印 4
  • 遇到 resolve 将 Promise 对象的状态设置为 fulfilled。
  • 遇到 setTimeout 将回调函数放入宏任务队列
  • 执行 then() 方法,创建一个新的 Promise 对象,将回调函数放入微任务队列
  • 遇到 console.log('7') 直接执行打印 7

此时第一轮执行结束 打印 1, 4 ,7。宏任务队列有两个任务。微任务队列有一个任务。
微任务优于宏任务执行接下来执行微任务队列

2. 接下来执行微任务队列

  • 进入微任务队列 遇到 console.log('6') 直接执行打印 6

此时微任务队列执行结束。宏任务队列有两个任务。微任务队列没有任务。

3. 接下来执行宏任务队列

  • 进入宏任务队列遇到 Promise.resolve().then 将回调函数放入微任务队列
  • 遇到console.log('3') 直接执行打印 3

此时 宏任务队列剩下一个任务。微任务队列有一个任务。
微任务优于宏任务执行接下来执行微任务队列

4. 接下来执行微任务队列

  • 进入微任务队列 遇到 console.log('2') 直接执行打印 2

此时微任务队列执行结束。宏任务队列有一个任务。微任务队列没有任务

5. 接下来执行宏任务队列

  • 进入宏任务队列 遇到 console.log('5') 直接执行打印 5

全部执行完毕。打印顺序:1, 4, 7, 6,3,2,5


Event Loop 的工作流程

  • JavaScript 引擎执行当前的同步代码,并将相应的函数调用添加到执行栈中,依次执行这些函数。
  • 当 JavaScript 引擎遇到一个异步操作时,它会将该操作添加到任务队列中,并继续执行后续的同步代码。
  • 当执行栈中的所有函数执行完毕时,JavaScript 引擎会检查任务队列中是否有待执行的任务。如果有,它会将队列中的第一个任务添加到执行栈中,并执行该任务对应的函数。
  • JavaScript 引擎重复上述步骤,直到任务队列为空。

再简单总结

  • 先执行同步任务再执行异步任务中的回调。
  • 异步任务又分为 宏任务微任务
  • 先执行微任务再执行宏任务
  • 以上不断循环♻️

Nice 我理解就这样了 等发现有啥错再改

Github Page 折腾记

场景: 这个账号之前用的新浪的邮箱,长时间没登录清掉浏览器缓存后密码给忘掉了。找回密码的过程简直痛苦。
新浪的邮箱那边太古老时间太长,邮箱密码早忘了,手机号也早就换,绝望 🤖。找回新浪邮箱密码又是要下微博、又是要验证手机号,
关键是之前的手机号还给忘记了。最后折腾来折腾去终于登录上邮箱。找回了github的密码。所以将前段时间新注册的账号仓库合并过来。

找回密码第一件事就是改邮箱 新浪真是太坑了


开始想合并账号但是看到有些复杂所以选择移交仓库

仓库正常移交后发现 Github Page 一直处于deploy状态 百度谷歌一圈也没有找到合理的原因
想着会不会是移交仓库后的Github Action的权限问题或者是Action中账号邮箱影响。但是仔细找了编译的过程没有发现错误


Long Long Time...

等了很久一直 在 wating deploy 尝试了改action、重新push、改权限,试了很多办法一直都不行。

终于想到 Vercel 绑定的是之前的github账号,而这个账号没有绑定过 Vercel !😑

一顿操作,删除之前绑定的账号重新绑定现在的账号
终于成功了!项目成功跑起来了!
🎉

搬家了!

搬家了!找了俩周末,被坑了1700块,总算尘埃落定。告别住了5年的青浦区,告别了俩基情四射的室友。感觉还是挺幸运,毕业之后遇到了一个很合得来的室友,一起住了将近5年。也感觉有些可惜,离开了能让我很轻松跑步的那么完美的小区公园。


今天打开Keep发现近两年跑量累计 889 公里了,还是疫情将近1年没运动情况下。再前面四年跑的比较疯,累计跑量应该超过了4000公里估计上5000了。这些年还是跑了不短的距离。不过现在比较佛系,有时间就慢慢跑跑,不追求配速,也不追求距离,能让心情舒畅就行。


接下来的计划就先考考证,重新搞几个小程序上线。还要学学英语,拖得太久了。去年阅读量也大降,把之前几本读了一半就扔了的书还要看完。当然还想出去逛逛,有几个地方也心心念很久了。


设计模式之发布订阅者模式

发布订阅者模式是一种行为设计模式

发布订阅者模式(Publish-Subscribe pattern)是一种常见的设计模式,也被称为观察者模式(Observer pattern)。在这种模式中,发布者(Publisher)和订阅者(Subscriber)之间通过一个被称为事件总线(Event Bus)的中介者进行通信。当发布者发布一个事件时,事件总线会将该事件传递给所有订阅者,订阅者可以根据自己的需求选择性地接收和处理这些事件。

根据以上内容实现的发布订阅者模式代码

const EventBus = (function(){
    let topics = {}, offEvents ={}, uuid = 0;
 
    function subscribe (topic, callback, once) {
        /**
         * topic  被订阅的内容的key值
         * callback 订阅者传入的订阅事件
         * once 是否只订阅一次
         */

        uuid ++
        topics[topic] = topics[topic]
            ? [...topics[topic], { callback, uuid, once }]
            : [{ callback, uuid, once }]
        // 存在离线事件 则执行离线事件
        if(offEvents[topic]){
            publish(topic, ...offEvents[topic])
        }

        return uuid
    }

    function publish (topic, value) {
        /**
         * topic 被发布的内容的key值
         * value 发布者传入的订阅事件
         */
        if (topics[topic]) { 
            for (let i = 0; i < topics[topic].length; i++) {
                let item = topics[topic][i]
                item.callback(value); 
                // 只订阅一次 则执行之后销毁
                if (item.once) {
                    topics[topic].splice(i, 1)
                }
            }
            // 执行后将对应离线事件置空
            offEvents[topic] = null
        }else{
            // 先发布再订阅事件 则先存储为离线事件
            offEvents[topic] = [value]
        }
    }
 
    function unsubscribe(topic, callback){
        /**
         * topic 被取消订阅的内容的key值
         * callback 取消订阅者传入的订阅事件 | 订阅时返回的uuid | 默认取消所有订阅
         */
        if (topics[topic]) {
            let name = ''
            if(callback instanceof Function){
                name = 'callback'
            }
            if(typeof callback === 'number'){
                name = 'uuid'
            } 
            if(typeof callback === 'undefined'){
                name = 'undefined'
            }

            for (let i = 0; i < topics[topic].length; i++) {
                let fn = topics[topic][i][name] 
                if (fn === callback) {
                    fn ? topics[topic].splice(i, 1) : topics[topic].pop()
                }
            }   
        }
    }

    // 订阅一次 执行之后销毁
    function subscribeOnce(topic, callback){
        return subscribe(topic, callback, true)
    } 

    return {
        subscribe,
        publish,
        unsubscribe,
        subscribeOnce
    }  
})() 

  • 代码不够健壮等待修改

用Github Issues 写博客

今天尝试用Github Issues 功能来写博客啦!


之前尝试过 Github page 做静态博客,也尝试过 Github Issues。后来买了云服务就慢慢舍弃了,经过很长的这段时间发现 云服务用来做博客除了价格贵,好像没有什么优点了。梳理需求后发现我只是需要有个能用来记录学习、记录生活的地方。作为程序员,还有哪里比Github更适合的呢?之前一直在学习 在向内输入,接下来也要尝试向外输出一些东西。通过记录下自己的一些学习和生活经历当然还有一些自己思考,希望能变得更加优秀。笔芯♥️


  1. 发生错误 更新令牌权限
  2. 更新工作流读写权限
  3. 添加Node Action Job

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.