首页
Search
1
解决visual studio code (vscode)安装时没有选择安装路径问题
138 阅读
2
Linux 下 Bash 脚本 bad interpreter 报错的解决方法
131 阅读
3
Arch Linux 下解决 KDE Plasma Discover 的 Unable to load applications 错误
107 阅读
4
如何在 Clash for Windows 上配置服务
77 阅读
5
Uniapp如何引入自定义样式文件
75 阅读
clash
服务器
javascript
全部
游戏资讯
登录
Search
加速器之家
累计撰写
1,061
篇文章
累计收到
0
条评论
首页
栏目
clash
服务器
javascript
全部
游戏资讯
页面
搜索到
624
篇与
的结果
2024-10-21
再说仿微博的发布与删除
很久之前闲着没事仿照新浪微博的发布与删除,写过一次代码!那时主要是实现滑动的效果,不过代码却是非常的乱,html 与 css 样式混用等。可是这段代码也没怎么用过,就一直在那扔着。点击查看效果直到昨天下午,有一妹子说她想实现那种跟新浪微博似的那种效果,我才想起我原先也写过这个东西,不过因为那时的代码啊有段乱,也就没给妹子推荐。然后晚上回到家后,就把我一年前写的代码重新设计了一下,相对来说结构更加清晰了一些!新代码和旧代码都放在一个仓库里,不过这两个没有纠缠。旧代码就一个文件:microblog.html,剩下的全部都是新代码,若不想要旧的代码,删了这个文件就是。放上代码地址:github-microblog说下这次的重构主要都进行了哪些工作: 更新了 jQuery 的版本:由 1.7.1 升级到了 1.11.1,同时也废除了 live 方法,改用 on; 把 html, css 与 js 进行相互的分离,不再集合到一个文件里; 添加了字数的统计和限制,最多只能输入 140 个字; 添加了输入框为空或字符超过限制时的提示; 添加了表情的插入 这次重写也学到了很多的东西,比如 CSS3 中的 animation,字数的限制,表情的添加等。点击链接【新的效果页面】,看看重构后的效果。 1. CSS3 中的 animation # 在输入框为空时或者字数超过了限制,输入框就是闪两下进行提示,这是通过 CSS3 中的 animation 属性实现的。关于 animation 更多的介绍,可以参考这个链接,本文就不展开说明了,你可以通过此链接【CSS3 的 animation】查看 animation 更多详细的信息与使用,这里简单的介绍下 animation 的使用:.send .warning { background: #fff; animation: "wobble" 0.8s ease-in-out; } @keyframes wobble { 0% { background: #fff; } 25% { background: #ffc0cb; } 50% { background: #fff; } 75% { background: #ffc0cb; } 100% { background: #fff; } } animation 中的参数分别表示: 'wobble' : 动画的名称,随便定义 0.8s : 动画执行的总时间 ease-in-out : 动画执行的方式 在 wobble 的结构体里,有很多的百分比数字,这些就是在 0.8s 里的执行时间里的各个进度,我们可以定义每个当前进度展示怎样的属性。定义了样式,还要确定触发点是什么?当用户点击确定“发布”按钮或者使用 ctrl+enter 组合键时进行信息的校验,如果输入框为空或者字数超过了限制,那么 textarea 标签就添加 warning 类,执行完成后再去掉该类名。const obj = { timer: null, warning: function () { $("#say").addClass("warning"); this.timer && clearTimeout(this.timer); this.timer = setTimeout(function () { $("#say").removeClass("warning"); }, 800); }, }; 2. 字数的限制 # 字数的限制,叫实时显示剩余字数更加确切一些。在这里我是让 textarea 标签监听 keydown 事件实现的,这里为什么不选择监听 keypress 或 keyup 事件呢?因为: keypress 与 keydown 事件差不多,keydown 是监听按键按下事件,keypress 是监听按下与松开事件;但是 keypress 只能监听单个按键事件,不能监听组合按键。这里使用到了 ctrl+enter 组合按键提交,因此就不能使用 keypress 了;关于 keydown 和 keyup,假如在输入英文字符或者数字时,虽然按键一直没有松开,但是一直在进行输入(没有松开按键则表示 keydown 事件无限执行),那么如果使用 keyup 事件来计算剩余字数就不准确了。因此最终选择了keydown事件 每次执行 keydown 事件时,均获取 textarea 的值的长度,然后计算出剩余的字数,如果剩余字数为 0,则不再让用户进行输入。 3. 将内容添加到列表中 # 参考现在的 html 结构,每条留言都是一个 li 标签,因此插入新留言时,也是要插入一个 li 标签。正常情况下,应该是: 添加成为 ul 标签的第一个 li 标签 默认隐藏这个刚添加的 li 标签 使用 slideDown()、fadeIn()等函数显示出来 可是这里,在我的代码里,有一个很难理解的问题:需要添加的 li 标签必须添加成为第二个 li 标签,如果是添加成为第一个 li 标签,执行显示动画或者删除该留言时,会闪动一下,也不知道为什么? 不知有谁能解决下不?var $ul = $("#talklist"), $one = $( '' + word + '' + datetime + '
2024年10月21日
3 阅读
0 评论
0 点赞
2024-10-21
使用node更新google hosts
现在网上有不少提供 google hosts 的网址(本文的最后提供了几个 google hosts 的网站地址),当我们访问不了 google 时,就需要复制这个网站提供的 hosts 到我们本地的 hosts,在粘贴前还要在 C 盘一层一层的找到本地 hosts,比较麻烦。于是就想能不能通过运行一条命令就能把网站里的 hosts 更新到本地,刚开始想的是用 php 写的,不过在跟同学聊天的过程中,同学建议使用 node 来实现这个功能,简单方便,而且我对 php 的正则表达式也不是很熟,那就用 node 试试吧。我目前的环境是 windows,接下来的步骤大部分是按照 windows 操作系统进行操作的: 安装 node; 下载需要的集成包; 编写程序; 运行 1. 安装 node # 在官方的【下载链接】中,下载我们需要的链接,我选择的是下面这个类型。下载后,双击进行安装。在现在的 node 版本中,默认是 node 和 npm 一起安装的,不用再单独安装 npm 了。安装成功后,使用 win+r 打开 cmd 命令窗口,然后输入node -v查看当前 node 的版本号输入npm -v查看当前 npm 的版本号如果两个都能正确的输出版本号,就说明 node 和 npm 已经安装成功了。使用.mis类型的文件进行能够自动添加 node 和 npm 到 PATH 的环境变量中,让我们在任何的目录下都能使用这两个命令。 2. 下载需要的集成包 # npm 是一个 node 的包管理和分发工具,已经成为了非官方的发布 node 模块(包)的标准。有了 npm,可以很快的找到特定服务要使用的包,进行下载、安装以及管理已经安装的包。使用 npm 进行模块的安装非常的方便:npm install ****,如果想安装成全局的,所有的项目都能使用,可以添加上-g参数,如:npm install -g ****。本项目中主要使用到的模块有: request : 远程 url 请求 cheerio : 类似于 jQuery,能够像 jQuery 那样选择元素,获取元素的内容 fs : 这是 npm 里自带的,不用下载安装,主要用于文件的读写操作 3. 编写程序 # 程序的逻辑很简单: 获取远程 url 的网页内容; 解析出网页内容中 hosts 部分; 读取自己设置的一些 hosts; 讲自己的 hosts 和远程获取到的 hosts 一起写入到 C 盘的 hosts 文件中。 这里使用了 async 中的 waterfall(瀑布流)来控制整个代码的流程。async.waterfall( [ function (callback) { self.log("正在连接 hosts url...."); callback(error, data); }, function (body, callback) { self.log("正在解析数据...."); callback(null, text); }, function (text, callback) { self.log("读取本地文件...."); callback(err, data); }, function (text, callback) { self.log("正在写入hosts...."); if (err) { self.log("写入失败...."); } else { self.log("写入成功...."); } calllback(err); }, function () { self.log("运行完毕!"); }, ], function (err, data) { console.log("err: " + err); // console.log('data: '+data); } ); async.waterfall 提供瀑布式的流控制。每个操作产生的数据可以传递给下一个函数,通过 callback 这个回调函数。async 模块保证回调只会被触发一次。它同时还为我们处理了错误,管理并行的任务。这里还要说明一下:我这儿有一个单独的文件来放置自己的 hosts,比如当前目录中的 default.txt 文件完整的代码可在github node-hosts下载 4. 运行代码 # 进入到这个项目所在的目录,首先运行npm install,安装程序所需要的集成包。安装完成之后,然后运行 index.js:node index.js。当然,这里还有一个问题要注意,hosts 文件需要有可读写的权限,不然 hosts 是无法进行修改的。程序采用的更新 hosts 的方式是全覆盖写入,因此我们需要把自己配置的一些 hosts 写到一个文件里(如 default.txt)。当程序更新时,会首先读取 default.txt 里的 hosts 配置,然后与远程地址里的 google hosts 一起写入到本地的 hosts 文件中。代码里还有参数的默认配置:_option : { hostsurl : 'http://www.360kb.com/kb/2_122.html', // 请求地址 hostsfile : 'C:/Windows/System32/drivers/etc/hosts',// 本地hosts地址 localfile : './default.txt' // 默认hosts } 你可以直接修改这些变量,或者在调用 init()方法时传递你需要的参数,程序自然会覆盖掉默认参数:wzHosts.init({ hostsfile: "/etc/hosts", localfile: "/data/default.txt" }); 这样,本地里的 google hosts 就更新到了最新! 5. 总结 # 通过这次的 hosts 读写,学习到了不少的 node 知识,欢迎提出你们的意见和建议!
2024年10月21日
5 阅读
0 评论
0 点赞
2024-10-21
node-socket实现web的即时聊天系统
本文将使用 Node.js 加 web socket 协议打造一个网页即时聊天程序,其中将会使用到 express 和 socket.io 两个包模块,下面会有介绍。首先放出代码链接【github-wchat】 1. node 的安装与使用 # 关于如何安装 node,可以参考我的上篇文章【使用 node 更新 google hosts】,那篇文章比较详细的介绍了如何安装 node。 2. 聊天系统使用到的模块 # node 的火爆得益于其丰富的模块管理系统(npm),我们能够从这里获取到任何我们想要的模块,同时我们也能上传自己的模块。关于这个聊天项目,我们使用到了两个模块:express 和 socket.io,使用 npm 安装这两个模块即可npm install express npm install socket.io 安装成功之后,就需要使用 express 构建我们的 web 开发框架var express = require("express"), //引入express模块 app = express(), server = require("http").createServer(app), io = require("socket.io").listen(server); app.use("/", express.static(__dirname + "/www")); //指定静态HTML文件的位置 server.listen(80); 这样,我们把所有的前端文件放到 www 目录里就行,比如 html, css, js 和 images 等。更多关于 express 的信息,可以参考这里:express api 3. 简要介绍 node 的事件机制 # 其实在 node 中关于事件机制有很多的内容,这里主要讲解 emit 和 on 的使用:emit 是事件产生器,用来产生事件的,on 是事件接收器,用来接收事件的,那么这两个正好组成了一组。一个在前端产生,另一个在后端接收,或者相反。这样事件就能在前后端进行传递了,同时也能进行参数的传递。前端:// wchat.js socket.emit("login", { nickname: nickname, img: $img.attr("src") }); 后端:// server.js socket.on("login", function (obj) { if (User.hasExisted(obj.nickname)) { socket.emit("nickExisted"); } else { obj.uid = socket.id; User.info[socket.id] = obj; // 通知用户登录成功 socket.emit("loginSuccess", obj.uid); var s = { nickname: obj.nickname, user: User.info, len: User.getLength(), type: "login", }; // 通知其他人有新用户进入 io.sockets.emit("system", s); } }); 4. web 即时聊天的思路 # 4.1 用户的登录与退出: # 因为暂时没有使用数据库,用户只能临时输入用户名,只要跟之前的用户不重复就能使用。同时在本系统中,还增加了一个可选择自己头像的功能,然后与用户名一起提交到 server.js,server.js 中有一个数组专门来存储所有登陆的用户。后续会添加上数据库的功能,来验证用户,不必再使用数组保存用户。// 登陆 login : function(){ var nickname = $("#nickname").val(); if(nickname===""){ return; } var $img = $(".portrait .selected").find("img"); // 获取头像地址 socket.emit("login", {nickname:nickname, img:$img.attr("src")}); return false; } server.js 收到用户的登录信息后,先判断用户名是否重复,如果没有重复,则返回登陆成功的信息,同时提示其他用户有新用户加入,并更新在线用户列表。新用户验证成功后,在wchat 中的 userid 字段中保存从服务器返回的用户编号,获取所有的用户列表,然后就可以聊天了。socket.on("login", function (obj) { if (User.hasExisted(obj.nickname)) { socket.emit("nickExisted"); } else { obj.uid = socket.id; User.info[socket.id] = obj; socket.emit("loginSuccess", obj.uid); // 更新在线用户列表 var s = { nickname: obj.nickname, user: User.info, len: User.getLength(), type: "login", }; io.sockets.emit("system", s); console.log(obj.nickname + " 已接入"); } }); 4.2 用户发送信息给其他用户 # 用户登录成功后就可以发送消息了:// user_msg是用户要发送的消息 socket.emit("message", {msg:user_msg}, userid); 当然这之前还需要进行一些其他的检验,比如判断 wchat.userid 是否为空,若为空表示用户还没有登陆,不能进行发送;若输入框内没有内容,直接点击发送按钮,也不能向服务器发送请求。当所有的验证都通过了,就可以发送请求了。server.js 接收到message 发送过来的请求后,首先验证是否有 userid 这个用户,如果没有则返回提示“该请求非法”,否则就使用msg向所有人发出这个消息,这个消息里具体的字段有:{ "status": "success", "info": { "userid": "123", "nickname": "wenzi", "image": "xx.png", "msg": "hello, my name is wenzi" } } 前端接收到 msg 的请求后,判断 status 的值是否等于 success,若等于,则解析 info 字段,将这些信息追加到输入框中:if (result.status == "success") { var info = result.info; var $content = $(this.content); this.userid == info.uid && $content.addClass("louzhu"); $content.find("img").attr("src", info.img); $content.find(".name").html(info.nickname); $content.find(".timer").html(info.time); $content.find(".msg").html(info.msg); $(".record").find(".list").append($content); this.scroll(); // 保证滚动条在最底部 $("#msg").val("").focus(); } else { this.warning("认证失败"); } 到这里,最基本的聊天功能已经完成了。我们还以给这个聊天系统弄一些锦上添花的功能,比如可以修改文字的颜色和大小,发送图片等功能。 4.3 修改文字的颜色和大小 # 在 html 中插入颜色选择器和文字大小修改控件,让用户进行选择。 颜色选择器可以使用 html5 中提供的 input:type=color 标签,文字大小修改控件我采用的是 select 标签让用户进行选择。 12px 14px 16px 18px 20px 22px 当然用户也可以不选择,这两个都有默认值,文字颜色默认是#000000 ,文字大小默认是14px ,每次发送消息时,都获取一次这两个控件的值:socket.emit( "message", { msg: msg, color: $("#fontcolor").val(), size: $("#fontsize").val() }, userid ); 服务器接收到这些值后,可以先拼接好 html 后再返回到前端,或者直接把这些属性发送到前端,让前端进行拼接。 4.4 发送图片 # 上面已经实现了基本的聊天功能了,进一步,如果我们还想让用户可以发送图片,那程序便更加完美了。图片不同于文字,但通过将图片转化为字符串形式后,便可以像发送普通文本消息一样发送图片了,只是在显示的时候将它还原为图片。在这之前,我们已经将图片按钮在页面放好了,其实是一个文件类型的 input,下面只需在它身上做功夫便可。用户点击图片按钮后,弹出文件选择窗口供用户选择图片。之后我们可以在 JavaScript 代码中使用FileReader来将图片读取为 base64 格式的字符串形式进行发送。而 base64 格式的图片直接可以指定为图片的 src,这样就可以将图片用 img 标签显示在页面了。为此我们监听图片按钮的 change 事件,一但用户选择了图片,便显示到自己的屏幕上同时读取为文本发送到服务器。$("#fileupload").on("change", function () { //检查是否有文件被选中 var $this = $(this), files = $this[0].files; if (files.length != 0) { //获取文件并用FileReader进行读取 var file = files[0], reader = new FileReader(); if (!reader) { Chat.warning("您的浏览器不支持FileReader"); $this.val(""); return; } reader.onload = function (e) { //读取成功,显示到页面并发送到服务器 $this.val(""); var $img = $(''), img = $img[0]; socket.emit( "message", { msg: '', color: $("#fontcolor").val(), size: $("#fontsize").val(), }, Chat.userid ); // that._displayImage('me', e.target.result); }; reader.readAsDataURL(file); } }); 我们使用上面发送文字的事件来发送图片,然后再通过服务器分发到各个用户的聊天面板上。有时候我们发送会很大的图片,产生横向的滚动条,破坏掉布局,因此我们限制图片的高度:.chat .info_msg .msg img { max-width: 174px; } 之前不知道怎么实现点击查看原图,后来才发现,能够根据e.target.result构造出一个 jQuery 对象:$img,然后顺便得出 DOM 对象:var img = $img[0]。通过这个 img 能够获取图片原生的高度和宽度,然后将这个高度和宽度作为属性存储到 img 标签中。用户点击被等比例缩小的图片时,获取这个存储的宽度和高度,展示出来。 5. 总结 # 到这里,基本上所有的东西已经完成了,当然,还有很多改进的地方,会在以后慢慢补上。比如有:发送语音,添加数据库,使用 CSS3 进行窗口抖动,可以一对一聊天等。其实一对一聊天已经实现了个大概了,在shaobings_one 的分支上,只是目前只实现了前端的功能,还不能真正的发送消息。如果你有什么建议和意见,欢迎留言。
2024年10月21日
8 阅读
0 评论
0 点赞
2024-10-21
jQuery 的 promise
为了让前端们从回调的地狱中回到天堂,jQuery 也引入了 Promise 的概念。Promise 是一种令代码异步行为更加优雅的抽象,有了它,我们就可以像写同步代码一样去写异步代码。jQuery 从 1.5 版本开始实现了 CommonJS Promise/A 规范这一重量级方案,不过没有严格按照规范进行实现,有一些 API 上的差异。 1. 以前的 ajax # 1.1 原生的 ajax 写法 # 以前我们写 ajax 请求时,如果是用原生的 JavaScript 代码写呢,通常是这样的一种形式:var XHR = (function () { var obj = null; // xhr对象 function init() { create(); send(); } // 创建xhr对象 function create() { if (window.XMLHttpRequest) { obj = new XMLHttpRequest(); } else if (window.ActiveObject) { obj = new ActiveObject("Microsoft.XMLHTTP"); } echange(); } // 发送消息 function send() { var v = parseInt(Math.random() * 100); obj.open("get", "test.php?v=" + v, true); obj.send(null); obj.onreadystatechange = echange; } // 接收消息 function echange() { /* 0 (未初始化) 对象已建立,但是尚未初始化(尚未调用open方法) 1 (初始化) 对象已建立,尚未调用send方法 2 (发送数据) send方法已调用,但是当前的状态及http头未知 3 (数据传送中) 已接收部分数据,因为响应及http头不全,这时通过responseBody和responseText获取部分数据会出现错误 4 (完成) 数据接收完毕,此时可以通过通过responseBody和responseText获取完整的回应数据 */ if (obj.readyState == 4 && obj.status == 200) { var result = JSON.parse(obj.responseText); console.log(result); } } return { init: init, }; })(); 1.2 jQuery 的 ajax 写法 # 原生的 ajax 代码能比较清晰的看出 ajax 的流程,可是如果每次都写这么多的代码就会造成很多的不便。不过在 jQuery 中,已经对 ajax 的代码进行封装,使用 jQuery 的 ajax 时就不用写这么多的代码了。当然,我们自己也可以对原生的 ajax 代码进行封装。$.ajax({ url: "test.php", // 请求地址 data: { v: v }, // 发送的数据 dataType: "json", // 返回的数据格式 type: "get", // 请求的方式:get|post // 发送前执行 beforeSend: function () { console.log("beforeSend"); }, // 返回成功执行 success: function (result) { console.log(result); }, // 返回失败执行 error: function (err) { console.log(err); }, // 无论成功还是失败都会执行 complete: function () { console.log("complete"); }, // 状态码对应的操作 statusCode: { 200: function () { console.log("200, ok"); }, 404: function () { console.log("404, page not found"); }, }, }); 上面的代码中虽然列了很多的选项,但是不是所有的都能用到的,可以结合实际的例子进行相应的取舍。比如 beforeSend, statusCode 等,如果实在是用不到,也可以不写的。 1.3 多个 ajax 顺序请求时 # 在使用这样的 ajax 进行多次顺序请求时,我们会采用嵌套的方式来进行。// 首次ajax请求 $.ajax({ url: "test.php", success: function () { // 请求完成后进行下次的请求 $.ajax({ url: "test1.php", success: function () { // 进行下次的ajax请求 $.ajax({ url: "test.php", success: function () { // ... }, }); }, }); }, }); 如果有比较多的 ajax 请求时,我们发现这样的代码实在是不利于我们的阅读,而且造成以后代码的修改和维护很困难。那有没有一种写法,我们既能分开写 ajax 请求,又能顺序执行。当然有啦,一个比较简单的方式就是使用异步回调的方式:// 第一个ajax请求 function ajax(callback) { $.ajax({ url: "test.php", success: function () { callback(); }, }); } // 第二个ajax请求 function ajax1(callback) { $.ajax({ url: "test.php", success: function () { callback(); }, }); } // 将第二个ajax方法作为第一个方法的回调方法 // 如果有多个ajax请求时,可以调用多个回调方法 ajax(ajax1); // ajax(ajax1(ajax2)); 2. 现在的 ajax # Promise/Deferred 模式在 JavaScript 框架中最早出现于 Dojo 的代码中,被广为所知则来自于 jQuery 1.5 版本,该版本几乎重写了 ajax 部分,使得调用 ajax 时可以通过如下的形式进行:$.ajax({ url: "test.php" }) .success(function () {}) .error(function () {}) .complete(function () {}); 这使得即使不调用 success(), error()等方法,ajax 也会执行,这样的调用方式比预先传入的回调让人觉得舒适一些。在原始的 API 中,一个事件只能处理一个回调,而通过 Deferred 对象,可以对事件加入任意的业务处理逻辑,示例代码如下:$.ajax({ url: "test.php" }) .success(function () {}) .error(function () {}) .success(function () {}); Promise/Deferred 模式在 2009 年时被 Kris Zyp 抽象为一个提议草案,发布在 CommonJS 规范中,随着使用 Promise/Deferred 模式的应用逐渐增多,CommonJS 草案目前已经抽象出了 Promise/A、 Promise/B、Promise/D 这样典型的异步 Promise/Deferred 模型,这使得异步操作可以以一种优雅的方式出现。jQuery 的 1.5 版本之后,$.ajax()返回的就是 promise 对象,而且其他的 jQuery 对象也能通过调用 promise()返回一个 promise 对象。因此,上面的 ajax 可以写成这样:var promise = $.ajax({ url: "test.php" }); promise.success(function () { // success }); promise.error(function () { // error }); 不过在 1.8 版本之后,jQuery 已经不推荐 success(),error()和 complete()方法了,推荐使用 done(), fail()和 always(),分别对应着前面三个方法。修改如下:var promise = $.ajax({ url: "test.php" }); promise.done(function () { // done }); promise.fail(function () { // fail }); promise.always(function () { // always }); 我们也可以用 then()方法把 done()和 fail()合并到一起。promise.then( function () { // done }, function () { // fail } ); 第一个参数表示 done 方法,第二个方法表示 fail 方法;如果只传递一个参数的话,就表示 done 方法。同时在 jQuery 中还提供了$.when()方法 $.when(deferreds) : 提供一种方法来执行一个或多个对象的回调函数, Deferred(延迟)对象通常表示异步事件 如果向 jQuery.when() 传入一个延迟对象,那么会返回它的 Promise 对象(延迟方法的一个子集)。可以继续绑定 Promise 对象的其它方法,例如, defered.then 。当延迟对象已经被受理(resolved)或被拒绝(rejected)(通常是由创建延迟对象的最初代码执行的),那么就会调用适当的回调函数。$.when($.ajax({ url: "test.php" })).then(function (data, status, jqXHR) { // done // console.log(data, status, jqXHR); }); 在案例中有多个延迟对象传递给 jQuery.when() ,该方法返回一个新的“宿主”延迟对象,跟踪所有已通过 Deferreds 聚集状态。 当所有的延迟对象被受理(resolve)时,该方法才会受理它的 master 延迟对象。当其中有一个延迟对象被拒绝(rejected)时,该方法就会拒绝它的 master 延迟对象。如果 master 延迟对象被受理(resolved),那么会传入所有延迟对象的受理(resolved)值,这些延迟对象指的就是传给 jQuery.when 的参数。例如,当延迟对象是 jQuery.ajax() 请求,那么传入的受理(resolved)参数就是请求用的 jqXHR 对象,传入顺序就是它们在参数列表中的顺序。在多延迟情况下,如果延迟一被拒绝,jQuery.when 触发立即调用 master 延迟对象的 failCallbacks。请注意,在上述情况中,有一些延迟对象依然是不能被受理(unresolved)的。那么,在这种情况下,如果需要执行一些额外的处理,例如,取消所有未完成的 ajax 请求,你可以在闭包中进行保持 jqXHR 对象的引用,并且在 failCallback 中检查或取消它们。$.when($.ajax({ url: "test.php" }), $.ajax({ url: "test1.php" })) .done(function (result, result1) { console.log(result); console.log(result1); }) .fail(function (err) { console.log("error"); }); 当两个 ajax 都执行成功时就会调用 done 方法,否则只要其中一个失败就会执行 fail 方法。 3. promise 对象使用的其他场景 # promise 对象不只是能在 ajax 中使用,在其他有时间延迟的地方也能够使用,比如animate(), fadeIn(), fadeOut() 等,我们想在 fadeIn()之后执行 animate(),然后执行 fadeOut 让他隐藏。一种方法就是使用这个方法提供的回调函数,来确保它的先后顺序:.process { background: #ccc; display: none; width: 150px; height: 150px; } // 记得加载jQuery库 $(".process").fadeIn(function () { $(this).animate({ width: "300px", height: "300px" }, 1000, function () { $(this).fadeOut(); }); }); 还有就是用上面讲到的 promise 对象。$(".process") .fadeIn() .promise() .then(function () { $(this).animate({ width: "300px", height: "300px" }, 1000); }) .then(function () { $(this).fadeOut(); });
2024年10月21日
4 阅读
0 评论
0 点赞
2024-10-21
leetcode-rotate-array
这是leetcode的一道算法题目,主要是讲解数组的旋转。【189-Rotate Array】 Rotate an array of n elements to the right by k steps.For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].Note:Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem. 题目的主要是意思是:向右旋转一个有n元素的数组k个步骤;比如一个数组的长度n=7, 移动的步数k=3,数组[1, 2, 3, 4, 5, 6, 7],旋转之后的数组为[5,6,7,1,2,3,4]。从题目中我们能够知道,其实我们没有必要移动k个步骤,移动k%n个步骤就行了,因为中间的一些步骤都是重复循环。我们只需要移动最后一个循环中剩余的几步即可完成,这样就能减少很多的步骤和操作。leetcode能够选择多个编程进行回答,而我选择的是JavaScript,不过使用JavaScript进行编程时,里面有个提示非常的重要:/** * @param {number[]} nums * @param {number} k * @return {void} Do not return anything, modify nums in-place instead. */ 如果用JavaScript的话,那么你的程序必须是:不用返回任何数据,而且,只能修改nums,不能替换nums的数据,比如:nums=***。刚开始没有注意到这句话,就想着,把最后k个数获取到,然后跟剩余的拼接起来,并赋值给nums即可。于是就产生了下面的程序:var rotate = function(nums, k) { var len, after; len = nums.length; k = k%len; // 对k进行处理 after = nums.splice(-k, k); // 截取最后k个元素 nums = after.concat(nums); // 最后k个元素与前面剩余的元素拼接起来 }; 用这个程序竟然没有通过,后来才注意到这个提示。我们只能对nums数组进行操作,即我们必须使用一些能够改变数组本身的方法,比如push(), pop, shift(), unshift(), splice()等;而slice(), concat()等这些方法是不能使用的,因为它们只是返回了我们需要的数据,但是原数组并没有发生改变。现在让我们回忆一下这些方法的使用: push(elem0, elem1, elem2, ...) 向数组的末尾添加元素,并返回新的长度 pop() 删除数组中最后的一个元素,同时返回该元素 shift() 把数组的第一个元素从其中删除,并返回第一个元素的值 unshift(elem0, elem1, elem2, ...) 向数组的开头添加一个或更多元素,并返回新的长度 splice(start, len, elem0, elem1, elem2, ...) 从数组的start位置删除len个元素,同时在该位置填充elem0, elem1等元素。如果elem为空,则直接进行删除,同时返回被删除的元素(array) slice(start, len) 从数组的start位置删除len个元素,同时返回被删除的元素,而原数组不变 concat(array) 在数组的后面接上一个数组array,同时返回拼接完成的数组,而原数组不变 从上面的各个方法中,我们能够看到,只能使用前面5个方法,最后2个方法不能修改原数组。因此现在的思路修改为:使用splice()得到最后的k个元素,然后使用unshift()把得到的数据一个个填充到数组的前面/** * @param {number[]} nums * @param {number} k * @return {void} Do not return anything, modify nums in-place instead. */ var rotate = function(nums, k) { var len, after; len = nums.length; k = k%len; after = nums.splice(-k, k); // 得到最后k个元素 for(var i=k-1; i>=0 ;i--){ nums.unshift(after[i]); // 填充到数组的开始位置 } };
2024年10月21日
5 阅读
0 评论
0 点赞
1
...
10
11
12
...
125