yarn
yarn 是由 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,yarn 是为了弥补 npm 的一些缺陷而出现的。
yarn 是由 Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具,yarn 是为了弥补 npm 的一些缺陷而出现的。
https://github.com/Redocly/redoc redoc自己号称是一个最好的在线文档工具。它支持swagger接口数据,提供了多种生成文档的方式,非常容易部署。使用redoc-cli能够将您的文档捆绑到零依赖的 HTML文件中,响应式三面板设计,具有菜单/滚动同步。
node this总结: 1,类的method指向的是当前对象 2,在node 中函数里的this 指向global 3,在浏览器中this 指向window 4,()=>{} 默认会绑定当前作用域的 this https://www.yisu.com/zixun/691554.html https://blog.csdn.net/weixin_44154094/article/details/120006139 https://www.bbsmax.com/A/x9J2YxOZz6/
在js和jquery使用中,经常使用到页面加载完成后执行某一方法。通过整理,大概是五种方式(其中有的只是书写方式不一样)。
{ ops: [ { insert: ‘Gandalf’, attributes: { bold: true } }, { insert: ‘ the ‘ }, { insert: ‘Grey’, attributes: { color: ‘#cccccc’ } } ] }
npm升级package.json依赖包到最新版本号 1、安装: npm install -g npm-check-updates 2、使用:
Mocha 是一个功能丰富的Javascript测试框架,它能运行在Node.js和浏览器中,支持BDD、TDD、QUnit、Exports式的测试, 安装 npm install mocha -g
在一个应用(domain: A)的某个page中, 通过IFrame的方式嵌入另一个应用(domain: B)的某个页面. 当两个应用的domain 不一样时, 在被嵌入的页面中不允许使用cookie(即使用cookie实现的session会失效). 在XP SP2和IE6之后,从安全性角度考虑,默认状态下不允许在iframe里使用跨站点cookie。
CodeMirror is a versatile text editor implemented in JavaScript for the browser. It is specialized for editing code, and comes with over 100 language modes and various addons that implement more advanced editing functionality. Every language comes with fully-featured code and syntax highlighting to help with reading and editing complex code.
protocol 属性是一个可读可写的字符串,可设置或返回当前 URL 的协议。
函数组件中没有生命周期,那么可以使用 useEffect 来替代。如果你熟悉 React class 的生命周期函数,你可以把 useEffect Hook 看做 componentDidMount,componentDidUpdate 和 componentWillUnmount 这三个函数的组合。
ClientA首先创建PeerConnection对象,然后打开本地音视频设备,将音视频数据封装成MediaStream添加到PeerConnection中。 ClientA调用PeerConnection的CreateOffer方法创建一个用于offer的SDP对象,SDP对象中保存当前音视频的相关参数。ClientA通过PeerConnection的SetLocalDescription方法将该SDP对象保存起来,并通过Signal服务器发送给ClientB。 ClientB接收到ClientA发送过的offer SDP对象,通过PeerConnection的SetRemoteDescription方法将其保存起来,并调用PeerConnection的CreateAnswer方法创建一个应答的SDP对象,通过PeerConnection的SetLocalDescription的方法保存该应答SDP对象并将它通过Signal服务器发送给ClientA。 ClientA接收到ClientB发送过来的应答SDP对象,将其通过PeerConnection的SetRemoteDescription方法保存起来。 在SDP信息的offer/answer流程中,ClientA和ClientB已经根据SDP信息创建好相应的音频Channel和视频Channel并开启Candidate数据的收集,Candidate数据可以简单地理解成Client端的IP地址信息(本地IP地址、公网IP地址、Relay服务端分配的地址)。 当ClientA收集到Candidate信息后,PeerConnection会通过OnIceCandidate接口给ClientA发送通知,ClientA将收到的Candidate信息通过Signal服务器发送给ClientB,ClientB通过PeerConnection的AddIceCandidate方法保存起来。同样的操作ClientB对ClientA再来一次。 这样ClientA和ClientB就已经建立了音视频传输的P2P通道,ClientB接收到ClientA传送过来的音视频流,会通过PeerConnection的OnAddStream回调接口返回一个标识ClientA端音视频流的MediaStream对象,在ClientB端渲染出来即可。同样操作也适应ClientB到ClientA的音视频流的传输。 https://www.cnblogs.com/fangkm/p/4364553.html
用 ts 写的模块在发布的时候仍然是用 js 发布,这就导致一个问题:ts 那么多类型数据都没了,所以需要一个 d.ts 文件来标记某个 js 库里面对象的类型
https://jsfiddle.net/1f8ckg90/ https://github.com/jsfiddle/togetherjs 这个工具可以有效的帮助web前端开发人员来有效分享和演示前端效果,大家可以在blog和论坛里用jsFiddle解答或者提问。
在任意对象和Object.prototype之间, 存在着一条以非标准属性__proto__进行连接的链, 我们将这条链称为原型链, 在默认情况下,一个任意的对象的原型是Object.prototype
改造可行性: electron应用也是在web项目上套了一层应用壳而已,所以移植到混合应用hybird上面,通过webview支持web显示也是可行的,所以!改造只要在浏览器上面跑得通就行!但是有些功能可能会稍有不同,需要做依据需求删除。
总的来说,WebRTC现在已经覆盖所有的现代浏览器了。 https://webrtc.org.cn/webrtc-in-browsers/ peer-to-peer communications and video-conferencing in HTML covered by this specification:
实现 coroutine 的方式有很多,比如 ES6 的 generator,ES7 的 async/await。而 tj 大神开发的 co 模块,也是取名字 coroutine 的缩写。 coroutine 需要底层的支持,对于不支持 generator/async/await 的平台来说,需要编译为 es5 代码。
webpack是一款模块加载器兼打包工具,把JS、样式,图片都作为模块来使用和处理。项目下有个配置文件webpack.config.js,用来告诉webpack需要做什么,本项目的webpack.config.js文件内容如下:
https://ace.c9.io/ https://github.com/chairuosen/vue2-ace-editor https://github.com/chairuosen/vue-ace-editor-demo/tree/vue2 https://github.com/ajaxorg/ace/
http://yslow.org/ Yslow-23条规则编辑 播报 [3] 1. 减少HTTP请求次数 合并图片、CSS、JS,改进首次访问用户等待时间。
对象的状态不受外界影响 (3种状态) Pending状态(进行中) Fulfilled状态(已成功) Rejected状态(已失败) 一旦状态改变就不会再变 (两种状态改变:成功或失败) Pending -> Fulfilled Pending -> Rejected
https://github.com/siimon/prom-client 这是一个支持histogram, summaries, gauges and counters四种数值格式的prometheus nodejs客户端。 停止轮询默认metrics
An EventSource instance opens a persistent connection to an HTTP server, which sends events in text/event-stream format. The connection remains open until closed by calling
https://github.com/socketio/engine.io https://github.com/socketio/socket.io-redis-adapter https://github.com/socketio/socket.io-client https://github.com/Terry-Mao/goim
https://quilljs.com/docs/modules/keyboard/ https://github.com/quilljs/quill https://quilljs.com/ https://www.jianshu.com/p/01a1a7029276 中文文档 https://kang-bing-kui.gitbook.io/quill/wen-dang-document/delta https://quilljs.com/playground/#autogrow-height
https://www.npmjs.com/package/@dreamworld/deep-object-diff
斧子演示 http://axeslide.com,我们团队开发的,演示效果和上面提到Prezi效果一样,不同的是我们的软件是基于H5开发的,完全免费,同时支持移动端浏览器播放,无需安装app、Flash插件。支持图表插入和编辑,支持svg,支持导出视频,支持gif文件,支持排版对齐,图像等大小等。不必在纠结中文字体,破解的问题。 https://www.zhihu.com/question/20204473
运行npm install webpack -g,重新安装webpack。 https://www.cnblogs.com/diweikang/p/9461530.html
npm install vue npm install –global vue-cli vue init webpack exp3 cd exp3 npm install npm run dev
Vue.js 是构建客户端应用程序的框架。默认情况下,可以在浏览器中输出 Vue 组件,进行生成 DOM 和操作 DOM。然而,也可以将同一个组件渲染为服务器端的 HTML 字符串,将它们直接发送到浏览器,最后将这些静态标记”激活”为客户端上完全可交互的应用程序。
https://zhuanlan.zhihu.com/p/272499379 https://github.com/quilljs/quill https://quilljs.com/ 文档: http://doc.quilljs.cn/1409370 体验: https://codepen.io/liuwave/pen/wvBwqod
注意Generator、yield;async、await要配套使用,且yield 的外层的函数一定要声明称Generator () 为了解决异步的嵌套问题,真是操碎了心,先是出了个Promise,然后又是Generator、yield组合,直到ES7的async、await组合。 Generator 生成器对象是由function 返回的,并且符合可迭代协议和迭代器协议。 这里有几个概念生成器、可迭代协议、迭代器协议。具体的概念可以点击链接查看MDN文档。
https://www.kancloud.cn/aibabel/koafornodejs/1812621 中间件工作原理 初始化koa实例后,我们会用use方法来加载中间件(middleware),会有一个数组来存储中间件,use调用顺序会决定中间件的执行顺序。 每个中间件都是一个函数(不是函数将报错),接收两个参数,第一个是ctx上下文对象,另一个是next函数(由koa-compose定义) 在建立好http服务器后,会调用koa-compose模块对middleware中间件数组进行处理。具体代码这里就不贴了,原理就是:会从middleware数组中取第一个函数开始执行,中间件函数中调用next方法就会去取下一个中间件函数继续执行。每个中间件函数执行完毕后都会返回一个promise对象。(ps:调用next方法并不是表示当前中间件函数执行完毕了,调用next之后仍可以继续执行其他代码) /**
// 实例化 let app = new Koa();
// Koa中间件 // 匹配任何路由,如果不写next,这个路由被匹配到了就不会继续向下匹配
// www.域名.com/news app.use(async (ctx, next) => { console.log(‘1、这是一个中间件01’); await next();
console.log(‘5、匹配路由完成以后又会返回来执行中间件’); })
app.use(async (ctx, next) => { console.log(‘2、这是一个中间件02’); await next();
console.log(‘4、匹配路由完成以后又会返回来执行中间件’); })
router.get(‘/’, async (ctx) => { ctx.body = ‘首页’; })
router.get(‘/news’, async (ctx) => { console.log(‘3、匹配到了news这个路由’); ctx.body = ‘这是一个新闻页面’; })
router.get(‘/login’, async (ctx) => { ctx.body = ‘登录页面’; })
app.use(router.routes()); app.use(router.allowedMethods()); /**
app.listen(3000);
sso(单点登录) 单点登录 的相关概念就不累述了,通俗的讲就是一次登录,到处有效,免去你在不同的服务间跳转时的繁琐验证。比如某宝网站是很多个系统相互调用形成的,如果没做单点登录的话,你每跳转一个服务,都需要验证身份,想想就可怕
JWT全称是jsonwebtoken,JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源
http://bluebirdjs.com/docs/getting-started.html https://github.com/petkaantonov/bluebird
npm install –save-dev node-sass 1 安装好依赖后, node_modules 文件夹下 .bin 就出现了node-sass 文件,
当您操作由客户端访问的Web服务时,可能难以将请求(客户端可以看到)与服务器日志(服务器可以看到)相关联。 X-Request-ID的想法是,客户端可以创建一些随机ID并将其传递给服务器。然后,服务器在其创建的每个日志语句中包含该ID。如果客户端收到错误,它可以将ID包含在错误报告中,允许服务器运算符查找相应的日志语句(而不必依赖于时间戳,IP等)。
权限认证基础:区分Authentication,Authorization以及Cookie、Session、Token
如果我们在外部js文件中直接require(‘slib’),nodejs会自动: 1)看它内置模块中是否有,如果有就优先加载内置模块 2)如果没有就看是否是“路径级”的引用 3)以上都不是就会在node_modules寻找同名文件夹。首先会默认寻找index.js,如果没有则会查看是否在package.json中做了main定义 内置模块如require(‘http’),路径级如require(‘./xxx.js’),注意这里的./代表的是当前js文件所在的目录,.js可写可不写,在下载gulp时由于包跟包之间有引用,因此会下载其他一些插件。 我们也可以在node_modules里自定义插件,如在node_modules里新建一个文件夹,里面的js文件一定要定义成index.js,这样当我们引用这个js文件时,node会自动加载这个文件下的index.js 5.自定义插件
项目根目录下新建.vscode文件夹,同时该文件夹下新建launch.json文件 { “configurations”: [ { “type”: “node”, “request”: “launch”, “name”: “nodemon”, “runtimeExecutable”: “nodemon”, “program”: “${workspaceFolder}/app/starter.js”, “restart”: true, “console”: “integratedTerminal”, “internalConsoleOptions”: “neverOpen” } ] } 1.需要在项目跟目录下,不然点击启动调试的时候识别不出来该项目中有这个调试任务
什么是回调地狱 异步的JavaScript程序,或者说使用了回调函数的JavaScript程序,很难地去直观顺畅地阅读,大量的代码以这种方式结束: fs.readdir(source, function (err, files) { if (err) { console.log(‘Error finding files: ‘ + err) } else { files.forEach(function (filename, fileIndex) { console.log(filename) gm(source + filename).size(function (err, values) { if (err) { console.log(‘Error identifying file size: ‘ + err) } else { console.log(filename + ‘ : ‘ + values) aspect = (values.width / values.height) widths.forEach(function (width, widthIndex) { height = Math.round(width / aspect) console.log(‘resizing ‘ + filename + ‘to ‘ + height + ‘x’ + height) this.resize(width, height).write(dest + ‘w’ + width + ‘_’ + filename, function(err) { if (err) console.log(‘Error writing file: ‘ + err) }) }.bind(this)) } }) }) } }) 有没有看到这些以”})”结尾的金字塔结构?这个形状为“亲切地”称为回调地狱。 二、什么是callback(回调)? “callback”仅仅只是一种使用JavaScript函数的一种通用称呼。在JavaScript语言中,并没有一种特定的东西称之为“callback”,这个只是一种方便的称呼。不同于大部分立即返回结果的函数,这些使用callback的函数需要消耗一些时间才能返回结果。“asynchronous”(异步),或者简称为“async”仅仅表示需要花费一些时间,或者是“在未来发生,而不是现在”。通常情况下,callback仅仅用于操作I/O的时候使用到。比如下载、读写文件、与数据库交互等。 当调用一个普通的函数的时候,你可以这样使用返回值: var result = multiplyTwoNumbers(5, 10) console.log(result) // 50 gets printed out 然而,异步函数,也就是使用了callback函数的不会立刻返回任何东西。 var photo = downloadPhoto(‘http://coolcats.com/cat.gif’) // photo is ‘undefined’! 在这种情况下,下载gif文件会花费相当长的时间,而且你并不希望你的程序在等待下载结束的过程中处于“暂停”(也就是阻塞,block)状态。 相反,你可以把下载结束后需要执行的操作存放到一个函数中,这个就是callback(回调)!你提供了一个“downloadPhoto”的函数,并且这个函数会在下载完成的时候执行callback(call you back later)函数,并且传递photo参数(或者出错的时候返回一个错误信息)。 downloadPhoto(‘http://coolcats.com/cat.gif’, handlePhoto) function handlePhoto (error, photo) { if (error) console.error(‘Download error!’, error) else console.log(‘Download finished’, photo) } console.log(‘Download started’) 人们在尝试理解“callback”这个概念的最大困难之处在于,程序运行的过程中,程序中的代码,是怎么样按照规则执行的。在这个例子中,有三件主要的代码段会发生:首先 “handlePhoto”函数被申明,然后是“downloadPhoto”函数会被调用并且把“handlePhoto”函数作为回调函数“callback”参数传递进入,最后,打印一句话“Download started”。 要注意以下,“handlePhoto”并没有立即被调用,只是创建并且作为一个参数传递给了“downloadPhoto”。但是,一旦“downloadPhoto”函数执行完成之后,”handlePhoto“就会运行。这个取决于网络连接到底有多快。 这个例子试图说明两个重要的概念: (1)回调函数“handlePhoto”仅仅是一种“存放”操作的方式,而这些操作需要延迟一段时间之后进行。 (2)代码的执行规则并不是按照阅读代码的“从上到下”的方式去遵守的,代码执行会根据事情结束的时间跳转嵌套。 三、我们如何解决“回调地狱”? 回调地狱的产生往往来源于对编码练习的缺乏,幸运的是,写出更好的代码并不困难! 我们只需要遵循如下三个原则: (1)保持代码浅显易读 下面是一个杂乱的JavaScript代码,这个代码用于通过使用“ browser-request ”从浏览器想服务端提交一个Ajax请求: var form = document.querySelector(‘form’) form.onsubmit = function (submitEvent) { var name = document.querySelector(‘input’).value request({ uri: “http://example.com/upload”, body: name, method: “POST” }, function (err, response, body) { var statusMessage = document.querySelector(‘.status’) if (err) return statusMessage.value = err statusMessage.value = body }) } 这段代码有两个匿名函数,我们给他们赋上名字吧! var form = document.querySelector(‘form’) form.onsubmit = function formSubmit (submitEvent) { var name = document.querySelector(‘input’).value request({ uri: “http://example.com/upload”, body: name, method: “POST” }, function postResponse (err, response, body) { var statusMessage = document.querySelector(‘.status’) if (err) return statusMessage.value = err statusMessage.value = body }) } 正如你看到的,给函数进行命名是一件超级简单的事情,而且会立刻体验到几个好处: 1)感谢这些具有描述性意义的函数名称把,这些名称使代码更加容易地阅读; 2)当异常发生的时候,你会在异常堆栈中看到确切的函数名称,而不是“anonymous”之类的名字; 3)你可以把函数移动出去,并且通过名字去引用他们; 现在,我们把这两个函数移动到我们程序的最顶层:
document.querySelector(‘form’).onsubmit = formSubmit function formSubmit (submitEvent) { var name = document.querySelector(‘input’).value request({ uri: “http://example.com/upload”, body: name, method: “POST” }, postResponse) } function postResponse (err, response, body) { var statusMessage = document.querySelector(‘.status’) if (err) return statusMessage.value = err statusMessage.value = body } 注意一下,函数声明在这里被移动到了文件最底部,这个要感谢 function hoisting. (2)模块化 这个是最重要的部分:任何人都有能力创建模块。引用 Isaac Schlueter (来源于node.js项目)的话说: Write small modules that each do one thing, and assemble them into other modules that do a bigger thing. You can’t get into callback hell if you don’t go there. “编写一个个小的模块,每个模块完成一件事情,然后把他们组装起来,去完成一个更大的事情,回调地狱这个坑,你不去往那走,你是不会陷进去的”。 让我们从上面的代码中提取模板代码,然后通过拆分到一组文件中的方式,将这些模板代码组装成module。我会展示一个module的格式,这种格式既可以用于浏览器的代码,也可以用在服务端。 这个是一个新的文件,叫做“formuploader.js”,里面包含两个从前面代码中提取的两个函数: module.exports.submit = formSubmit function formSubmit (submitEvent) { var name = document.querySelector(‘input’).value request({ uri: “http://example.com/upload”, body: name, method: “POST” }, postResponse) } function postResponse (err, response, body) { var statusMessage = document.querySelector(‘.status’) if (err) return statusMessage.value = err statusMessage.value = body } 其中“module.exports”部分是一个node.js模块系统的一个例子,electron 和 浏览器 使用browserify 。我非常喜欢这种模块化,因为它可以工作在任何地方,而且非常简单,并且不需要复杂的配置文件或者脚本。 现在我们有了“formuploader.js”(并且已经作为一个脚本,在页面加载完成之后载入到了页面中),我们只需要“require”这个模块并且使用它!这个是一个我们的程序中具体代码的样子: var formUploader = require(‘formuploader’) document.querySelector(‘form’).onsubmit = formUploader.submit 这样,我们的程序仅仅需要两行代码,并且有如下的好处: 1)对于一个新的开发者来说,更加容易理解了 —— 他们不用深陷于“被迫通读全部“formuploader”函数”。 2)“formuploader”可以用于其他地方,不用重复编写代码,并且可以轻松地分享到github或者npm上去。 (3)处理每一个独立的异常 错误(error)有很多种类型:程序员犯的语法错误(往往在第一次尝试运行程序的时候会被发现);程序员犯的运行时错误(程序可以运行但是里面有一个bug会把事情弄糟);其他情况下的平台错误比如无效的文件权限,硬件驱动失效、网络连接异常等问题。这个部分主要针对最后一类错误(error)。 前面两条原则可以让你的代码具有可读性,但是这一条可以让你的代码保持稳定健壮。当你在使用回调函数(callback)的时候,讲道理你其实是在和任务打交道,这些任务都是被分发给回调函数,并且回调函数会在后台执行,然后这个任务要么执行成功,要么由于失败而终止。任何有经验的开发者都会告诉你:你永远不会知道错误是谁么时候会发生,你只有去假定他们会一直出现。 目前在回调函数中处理错误最流行的方式是Node.js风格:所有的回调函数的第一个参数永远是给“error”保留着。 var fs = require(‘fs’)
fs.readFile(‘/Does/not/exist’, handleFile)
function handleFile (error, file) {
if (error) return console.error(‘Uhoh, there was an error’, error)
// otherwise, continue on and use file
in your code
}
在第一个参数中使用“error”是一个简单方便的鼓励记得处理错误的一个方式。如果把这个参数放到第二的位置,你在写代码的时候往往会容易忽略第二个“error”参数,而只关注第一个参数,比如“function handleFile(file){}”。
Code linters(检查代码的小工具)也可以通过配置,实现提醒你要处理这些回调函数错误。最简单的一个小工具就是 standard。这个工具你仅仅只需要在你的代码文件的路径中执行 “$ standard”命令,它就会把你每一个没有进行错误处理的回调函数标记出来。
四、总结
1、不要嵌套函数。给这些函数进行命名,并且放到你的程序的最顶层。
2、使用 function hoisting(函数提升)机制将你的函数移到文件的末尾。
3、在每一个回调函数中去处理每一个错误。可以使用一个代码检查工具去帮你完成这个事情。
4、创建可以服用的函数,并且把他们放置在一个模块中,这样可以提高代码可读性。把代码分割成一个个小的部分,可以帮助你更好的处理error,测试,强迫你去为你的代码创建一个稳定的、文档完善的公共API模块,而且有助于代码的重构。
最重要的避免回调地狱的方面就是,移出你的函数,这样程序的流程可以更容易理解,新手也就不用去啃每一个函数究竟是干什么的。
从现在开始,你首先就可以把函数移到文件的底部,然后逐渐地把函数移到另一个文件中并且使用类似“require(‘./photo-helpers.js’)”的方式去关联,最终,把他们放进一个独立的模块比如“require(‘image-resize’)”.
下面是一些创建模块的一些原则:
1、通过把一些经常重复使用的代码封装成一个函数;
2、当你的函数(或者一组具有类似主题功能的函数)足够大的时候,移动到另一个文件,并且通过“module.exports“的方式去发布,你可以使用类似“require(‘./photo-helpers.js’)”的方式去关联这个文件。
3、如果你的代码可以用于很多个项目的时候,你需要提供“readme”文件、测试以及“package.json”文件,并且把他们发布到github和npm中。
4、一个优秀的模块是很小的而且只聚焦于一个问题;
5、JavaScript的模块中的一个独立的文件行数不应该超过150行;
5、在整个JavaScript的文件结构组织中,一个模块不应该拥有超过一层的嵌套文件夹。如果这种情况发生了,那么意味着整个模块要做的事情有点过多了。
6、让更有经验的程序员给你演示下好的模块构建的方式,直到你了解究竟什么是优秀的模块。如果有一个模块,你需要花不止几分钟的时间去了解它是干嘛的,那么这个模块并不是一个多么好