forzys / blog Goto Github PK
View Code? Open in Web Editor NEWAutomatic backup issues and generate Index
Home Page: https://blog.19941024.xyz/
Automatic backup issues and generate Index
Home Page: https://blog.19941024.xyz/
Promise 是 ES6 异步编程的一种解决方案 (目前最先进的解决方案是 async 和 await 的搭配(ES8),
但是它们是基于 promise 的),从语法上讲,Promise 是一个对象或者说是构造函数,
用来封装异步操作并可以获取其成功或失败的结果
最重要也是最主要的一个场景就是ajax 和axios 请求。
通俗来说,由于网速的不同,可能你得到返回值的时间也是不同的,
但是我们下一步要执行的代码依赖于上一次请求返回值,
这个时候我们就需要等待,结果出来了之后才知道怎么样继续下去。
防止出现回调地狱;
提高代码的可读性;
像同步操作那样去执行异步操作
1.pending: 等待中,或者进行中,表示还没有得到结果
2.resolved(Fulfilled): 已经完成,表示得到了我们想要的结果,可以继续往下执行
3.rejected: 也表示得到结果,但是由于结果并非我们所愿,因此拒绝执行
1. promise 其实就是一个对象或者说是构造函数
2. promise 的出现(es6) 就是解决异步编程和回掉地狱等问题,
async 和 await 的出现(ES8)就是基于 promise 的一种解决异步编程的终极解决方案(简化代码等等)
3. 在前端中,ajax 和 axios 都会用到异步编程,axios 更是基于 promise 的,
所以一定要掌握promise 以及用 async 和 await 搭配 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()
})
}
}
场景: master分支 cherry-pick testing分支的提交内容(commit)时发现有大量冲突
原因: 之前master分支cherry-pick过testing分支的内容 且解决了冲突之后push到master
解决方案:
优点:保留了提交修改的原始记录
缺点:master会出现两条cherry-pick的记录 (之前pick过一次的现在会重新pick一次)
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 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 // 关联远程分支
庄子·山木 <市南宜僚见鲁侯>
市南子答鲁侯
少君之费,寡君之欲,虽无粮而乃足。君其涉于江而浮于海,望之而不见其崖,愈往而不知其所穷。送君者皆自崖而反,君自此远矣!故有人者累,见有于人者忧。故尧非有人,非见有于人也。吾愿去君之累,除君之忧,而独与道游于大莫之国。方舟而济于河,有虚船来触舟,虽有惼心之人不怒,有一人在其上,则呼张歙之,一呼而不闻,再呼而不闻,于是三呼邪,则必以恶声随之。向也不怒而今也怒,向也虚而今也实。人能虚己以游世,其孰能害之!
虚船触舟的回答很发人深思
乘船来渡河,突然有条空船碰撞过来,即使心地最偏狭、性子最火急的人也不会发怒;倘若有一个人在那条船上,那就会人人大声呼喊喝斥来船后退;呼喊一次没有回应,呼喊第二次也没有回应,于是喊第三次,那就必定会骂声不绝。刚才不发脾气而现在发起怒来,那是因为刚才船是空的而今却有人在船上。一个人倘能听任外物、处世无心而自由自在地遨游于世,谁能够伤害他!
很有意思的是让人生气的原因不是船被撞而是船上是否有人。
很多时候我们并不是对事不对人,很多脾气也一开始就带入了自己的价值观世界观。
一旦对方的想法行为与自己期待的不一致,脾气立马就上来。 (撞船)
被踩一脚让自己很生气,可被小猫踩了一脚呢?
人能虚己以游世,其孰能害之!
很多时候,我们都应该把别人看成一个"空船"
项目地址:Telegraph-Image.
线上地址:image.19941024.xyz
项目地址:short.
线上地址:short.19941024.xyz
项目地址:epeius.
线上地址:**
项目地址:**.
线上地址:api.19941024.xyz
.parent {
display: flex;
flex-wrap: wrap;
}
.child{
flex: 0 0 calc(33.33% - 16px); /**(例如 N = 3) 100% / N - 间距 */
margin: 8px;
}
.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 就 排斥那个方向 */
}
.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是一款小巧的javascript模块打包工具,通过rollup打包后的代码,体积较小,而且没有冗余的代码
rollup提供了五种选项:
<script>
标签加载使用配置文件 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 启动配置项;
yarn add rollup --dev
npm install uglify-js -g
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]`
uglifyjs [input-file] -m -o [output-file]
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
发现一个十分小巧的Markdown解析库 但是十分古老 , 不支持Table、对Code的支持也十分不友好,还发现一些bug等等
所以动手添加了需要的一些功能
修改 pagedown 添加table支持 添加删除线 以及代码块等。
适合个人博客及其他简单的Markdown渲染 。
十分小巧 build后只有10k左右 gzip压缩后只有4k大小 没有其他复杂的功能 提供pluginHooks可自定义渲染内容
update:
添加hook以支持code语法高亮效果
Todo:
接下来继续修改bug 看看在实际项目中使用的效果如何
$ keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****
my-release-key.keystore
文件放到项目中的android/app
文件夹下项目目录/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
场景: 做渐变色背景切换的时候发现如果直接改变background
的 linear-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
那要怎么实现渐变背景的过渡效果呢?
网上找了一圈大概有这几种方法:
.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;
}
.box{
background: linear-gradient(to right, #f2f3f4, #a4907c);
background-size: 200%;
transition: background-position .3s;
}
.box:hover {
background-position: 100% 0;
}
.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;
}
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的支持情况
@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;
}
其他方式 例如利用动画属性也可以实现
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')
根据理解可以解上面的题:
执行栈
中的同步任务
console.log('1')
直接执行打印 1宏任务队列
console.log('4')
直接执行打印 4宏任务队列
微任务队列
console.log('7')
直接执行打印 7此时第一轮执行结束 打印 1, 4 ,7。宏任务队列有两个任务。微任务队列有一个任务。
微任务优于宏任务执行接下来执行微任务队列
微任务队列
微任务队列
遇到 console.log('6')
直接执行打印 6此时
微任务队列
执行结束。宏任务队列有两个任务。微任务队列没有任务。
宏任务队列
遇到 Promise.resolve().then
将回调函数放入微任务队列
console.log('3')
直接执行打印 3此时 宏任务队列剩下一个任务。微任务队列有一个任务。
微任务优于宏任务执行接下来执行微任务队列
微任务队列
console.log('2')
直接执行打印 2此时
微任务队列
执行结束。宏任务队列有一个任务。微任务队列没有任务
宏任务队列
console.log('5')
直接执行打印 5全部执行完毕。打印顺序:1, 4, 7, 6,3,2,5
同步任务
再执行异步任务
中的回调。异步任务
又分为 宏任务
与 微任务
。微任务
再执行宏任务
。Nice 我理解就这样了 等发现有啥错再改
场景: 这个账号之前用的新浪的邮箱,长时间没登录清掉浏览器缓存后密码给忘掉了。找回密码的过程简直痛苦。
新浪的邮箱那边太古老时间太长,邮箱密码早忘了,手机号也早就换,绝望 🤖。找回新浪邮箱密码又是要下微博、又是要验证手机号,
关键是之前的手机号还给忘记了。最后折腾来折腾去终于登录上邮箱。找回了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
}
})()
- 发生错误 更新令牌权限
- 更新工作流读写权限
- 添加Node Action Job
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.