ready相关知识
-
onload与ready的区别1 onload等页面全部加在完毕然后执行 ready()只要dom加载完毕就执行2 onload只能一个 ready()可以有多3 ready()可以简化成 $(function(){do sth...})
-
关于$(document).ready(function ())关于js和jq一直学的懵懵懂懂,看教程的时候有时候对于案例的意思是明白但是有的语句就不是很懂到底为什么这么写,在看抢车位$(document).ready(function ())是什么意思不是很懂(虽然这是一个很短的教程)查了一下终于初步明白了一些 以下: $(document).ready(function ());的缩写为 $(function(){}); 或 $().ready(function(){}) jQuer的默认参数是:“document” document.ready和onload的区别——JavaScript文档加载完成事件 页面加载完成有两种事件 一是ready,表示文档结构
-
jQuery学习之$(document).ready() 我的第一个错误: 1.$(document).ready(function() {});写与不写有什么区别 不写$(document).ready(function() {});,直接在<script></script>中写事件,方法可以吗?答:$(document).ready 里的代码是在页面内容都加载完才执行的,直接写到script标签里,当页面加载完这个script标签就会执行里边的代码了,如果标签里执行的代码调用了当前还没加载过来的代码或者dom,那么就会报错,当然如果把script标签当到页面最后面那么就没问题了和ready差不多的效果
-
如何解决JQuery中的ready函数冲突jQuery确实是一个提高前端开发效率的好框架(虽然很多大牛们都说它效率不咋地),但是用好它有时候并不容易,也许你也遇到过以下情况:一个aspx页面通常可以包含其它ascx控件,如果在多人协同开发的情况下:程序员小张在控件A.ascx中使用了 ().ready(function),而程序员小王又在控件B.ascx中也使用了ready函数,程序员小李在做页面时,把A.ascx,B.ascx都拖到自己的页面中,然后在页面中也需要用到().ready函数,这下好了:虽然jQuery本身的设计还算不错,document加载完成后会依次触发各个ready中定义的function(这一点很好,不象javascript中默认后面的同名函数会覆盖前面的函数定义),但是如果某个程序员希望自己的ready部分先执行(或者这三个程序员各自的ready处理有严格先后顺序时),这个怎么办呢?其实这个也不难,可以利用setTimeOut让某个程序员的ready部分延时执行:$().ready(function(){ &nb
ready相关课程
ready相关教程
- Redis安装: 首先需要安装并启动Redis的服务器,具体的不同系统的安装步骤,可参考慕课网关于 Redis 的学习资料进行操作,这里就不再赘述。启动 Redis 服务器需要运行命令:redis-server服务启动成功后,会显示 Ready to accept connections。效果展示:测试一下客户端能否使用redis-cli ping成功后,如下所示:
- 4. 配置 Worker 节点 在三个 Worker 节点上执行之前记录的增加节点指令Tips: 记得替换成自己操作环境中获取的指令kubeadm join 192.168.1.200:6443 --token 4hmk4a.4h0zrymxjmudhjmq \ --discovery-token-ca-cert-hash sha256:edf04a8954bb2729d8d603e14e802e72109ae10346503b5b283481ce08b02186耐心等待 3-5 分钟,在 master 节点执行kubectl get nodes -o wide查看节点详情,所有节点状态均为Ready。至此,K8s 集群已经初步搭建完成。
- 5. yield 方法和 sleep 方法的区别 sleep () 方法给其他线程运行机会时不考虑线程的优先级,因此会给低优先级的线程以运行的机会;yield () 方法只会给相同优先级或更高优先级的线程以运行的机会;线程执行 sleep () 方法后转入阻塞 (blocked) 状态,而执行 yield () 方法后转入就绪 (ready) 状态;sleep () 方法声明会抛出 InterruptedException, 而 yield () 方法没有声明任何异常;sleep () 方法比 yield () 方法具有更好的移植性 (跟操作系统 CPU 调度相关)。
- 3. 配置Master节点 使用宿主机的命令行工具 ssh 登录到 master-1 节点,先读取我们的 K8s 版本号:version=`cat .k8s.version`设定kubeadm配置文件kubeadm.yamlcat << EOF > kubeadm.yamlapiVersion: kubeadm.k8s.io/v1beta2kind: ClusterConfigurationcontrollerManager: extraArgs: horizontal-pod-autoscaler-use-rest-clients: "true" horizontal-pod-autoscaler-sync-period: "10s" node-monitor-grace-period: "10s"apiServer: extraArgs: runtime-config: "api/all=true"kubernetesVersion: "v$version"imageRepository: "registry.aliyuncs.com/google_containers"EOF使用此配置文件进行 master 节点安装部署:kubeadm init --config kubeadm.yaml等待一段时间,部署完成,它会给我们一段提示master-1上执行:mkdir -p $HOME/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configTips: 在worker节点上进行如下操作可以将节点添加到K8s集群,但现在还不急,先记下来。kubeadm join 192.168.1.200:6443 --token 4hmk4a.4h0zrymxjmudhjmq \ --discovery-token-ca-cert-hash sha256:edf04a8954bb2729d8d603e14e802e72109ae10346503b5b283481ce08b02186执行kubectl get nodes查看当前节点的状态:发现状态为NotReady,原因是我们尚未配置网络相关的插件,一些跟k8s服务相关容器无法连接到网络。常用的容器网络接口插件有 Flannel 、Calico、 Weave 等,这里我们选择简单易用的 weave 网络插件kubectl apply -f https://cloud.weave.works/k8s/net?k8s-version=$version安装完毕后,查看当前节点状态变为Ready。
- 4. Java NIO 服务器端实现步骤 因为服务端采用非阻塞模式,需要用到Java NIO 的 Selector 组件,这是 Java NIO 的 I/O 多路复用机制,可以同时监听多个 SocketChannel 是否有读写事件。创建 Java NIO 的 Selector 实例selector = Selector.open();打开服务器 ServerSocketChannelserverChannel = ServerSocketChannel.open();给 ServerSocketChannel 绑定监听的 socket 地址,监听 any_addr serverChannel.socket().bind(new InetSocketAddress(PORT));设置 SO_REUSEADDR 选项,作为服务器,这是基本的要求 serverChannel.socket().setReuseAddress(true);设置非阻塞模式,这是服务器的基本要求,也是本小节的重点 serverChannel.configureBlocking(false);向 Selector 注册 accept 事件 serverChannel.register(selector, SelectionKey.OP_ACCEPT, serverChannel);编写事件循环。所有需要读写数据的 SocketChannel,需要将读写事件注册到 Selector。调用 Selector 的 select 方法,调用线程会进入 I/O 事件监听状态。如果没有事件发生,调用线程会被阻塞,进入事件等待状态;如果有事件发生,Selector 的 select 方法会返回发生了 I/O 事件的 SocketChannel 个数。Selector 的 selectedKeys 方法返回一个 java.util.Set 类,集合中包含的是 SelectionKey 结构,SelectionKey 和 SocketChannel 是一一对应的,表示发生了 I/O 事件的 SocketChannel。所以需要 遍历 Set,分别处理每个 SelectionKey。 while (true) { int readyChannels = selector.select(); if (readyChannels == 0) { System.out.println("No socket has i/o events"); continue; } Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key != null) { } keyIterator.remove(); } }抽象一个内部类 Client,表示一个客户端连接,每当一个新连接建立的时候,创建一个此类的对象。private static class Client{ public void sendData(); public int recvData(); public void close();}通过 key.isAcceptable() 处理连接接收事件。if (key.isAcceptable()) { // a connection was accepted by a ServerSocketChannel. ServerSocketChannel ssc = (ServerSocketChannel) key.attachment(); SocketChannel newSock = ssc.accept(); newSock.configureBlocking(false); Client client = new Client(selector, newSock);} 通过 key.isReadable() 处理读事件if (key.isReadable()) { // a channel is ready for reading Client client = (Client) key.attachment(); int rc = client.recvData(); if (rc == 0) { client.sendData(); }}通过 key.isReadable() 处理“写”事件if (key.isWritable()) { // a channel is ready for writing Client client = (Client) key.attachment(); client.cancelEvent(SelectionKey.OP_WRITE); client.sendData();}服务器端完整代码如下:import java.io.*;import java.net.InetSocketAddress;import java.nio.ByteBuffer;import java.nio.channels.*;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Iterator;import java.util.Set;public class NonblockTCPServer { // 服务器监听的端口 private final static int PORT = 9082; private Selector selector = null; private ServerSocketChannel serverChannel = null; private static class Client{ // 接收 buffer 长度 private final static int RECV_BUF_LEN = 1024; // 接收buffer 声明 private ByteBuffer recvBuff = null; // 发送 buffer 长度 private static final int SEND_BUFF_LEN = 1024; // 发送 buffer 声明 private ByteBuffer sendBuff = null; // the Selector private Selector selector = null; // SocketChannel 引用声明,表示一个连接 private SocketChannel socketChannel = null; private SelectionKey sk_ = null; private boolean canSend = true; public Client(Selector selector, SocketChannel newSock){ this.selector = selector; this.socketChannel = newSock; this.recvBuff = ByteBuffer.allocate(RECV_BUF_LEN); this.sendBuff = ByteBuffer.allocate(SEND_BUFF_LEN); this.register(SelectionKey.OP_READ); } private void register(int op){ try { if (sk_ == null){ sk_ = this.socketChannel.register(selector, op, this); } else { sk_.interestOps(op | sk_.interestOps()); } } catch (ClosedChannelException e) { e.printStackTrace(); } } public void cancelEvent(int ops){ if (sk_ == null) return; sk_.interestOps(sk_.interestOps() & (~ops)); } public void sendData() { try { int totalSendBytes = 0; String resp = null; if (canSend){ //设置日期格式 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); resp = "The server time : " + df.format(new Date()); sendBuff.putInt(resp.length()); sendBuff.put(resp.getBytes()); totalSendBytes = resp.length() + 4; sendBuff.flip(); }else { totalSendBytes = sendBuff.remaining(); } int sbytes = this.socketChannel.write(sendBuff); System.out.println("Send to client about message :" + resp); if (sbytes < totalSendBytes) { this.register(SelectionKey.OP_WRITE); canSend = false; } else { if (!canSend){ canSend = true; } sendBuff.rewind(); } } catch (IOException e) { e.printStackTrace(); } } public int recvData(){ try { int recvBytes = this.socketChannel.read(this.recvBuff); if (recvBytes < 0){ System.out.println("Meet error or the end of stream"); close(); return -1; }else if (recvBytes == 0){ return 0;// eagain } this.recvBuff.flip(); while (this.recvBuff.remaining() > 0) { // Incomplete message header if (this.recvBuff.remaining() < 4) { break; } int bodyLen = this.recvBuff.getInt(); if (bodyLen > this.recvBuff.remaining()) { // Incomplete message body break; } byte[] body = new byte[bodyLen]; this.recvBuff.get(body, 0, bodyLen); System.out.println("Recv message from client: " + new String(body, 0, bodyLen)); } // flip recv buffer this.recvBuff.compact(); return 0; } catch (IOException e) { e.printStackTrace(); close(); } return -1; } public void close(){ try { cancelEvent(SelectionKey.OP_WRITE | SelectionKey.OP_READ); if (this.socketChannel != null){ this.socketChannel.close(); } } catch (IOException e) { e.printStackTrace(); } } } public void start(){ try { selector = Selector.open(); serverChannel = ServerSocketChannel.open(); // 绑定监听的 socket 地址,监听 any_addr serverChannel.socket().bind(new InetSocketAddress(PORT)); // 设置 SO_REUSEADDR 选项,作为服务器,这是基本的要求 serverChannel.socket().setReuseAddress(true); // 设置非阻塞模式,作为服务器,也是基本要求 serverChannel.configureBlocking(false); // 注册 accept 事件 serverChannel.register(selector, SelectionKey.OP_ACCEPT, serverChannel); } catch (IOException e) { e.printStackTrace(); stop(); } } public void process() { try { while (true) { int readyChannels = selector.select(); if (readyChannels == 0) { System.out.println("No socket has i/o events"); continue; } Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key != null) { if (key.isAcceptable()) { // a connection was accepted by a ServerSocketChannel. ServerSocketChannel ssc = (ServerSocketChannel) key.attachment(); SocketChannel newSock = ssc.accept(); newSock.configureBlocking(false); Client client = new Client(selector, newSock); } else if (key.isConnectable()) { // a connection was established with a remote server. } else if (key.isReadable()) { // a channel is ready for reading Client client = (Client) key.attachment(); int rc = client.recvData(); if (rc == 0) { client.sendData(); } } else if (key.isWritable()) { // a channel is ready for writing Client client = (Client) key.attachment(); client.cancelEvent(SelectionKey.OP_WRITE); client.sendData(); } } keyIterator.remove(); } } } catch (IOException e) { e.printStackTrace(); } } public void stop(){ try { if (serverChannel != null){ serverChannel.close(); serverChannel = null; } if (selector != null) { selector.close(); selector = null; } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { NonblockTCPServer tcp = new NonblockTCPServer(); tcp.start(); tcp.process(); }}对于非阻塞式 Socket,需要处理发送 Buffer 满和接收 Buffer 为空的情况。服务器样例代码的 320 ~ 390 行的主要逻辑就是在处理非阻塞模式下,发送 Buffer 满和接收 Buffer 为空的逻辑。
- 2.2 下载器实例的 handlers 属性值分析 重点先看看这个 handlers 属性值,它是 DownloadHandlers 类的一个实例,对应的代码位置为:scrapy/core/downloader/handlers/__init__.py 。其类定义如下:# ...class DownloadHandlers: def __init__(self, crawler): self._crawler = crawler self._schemes = {} # stores acceptable schemes on instancing self._handlers = {} # stores instanced handlers for schemes self._notconfigured = {} # remembers failed handlers handlers = without_none_values( crawler.settings.getwithbase('DOWNLOAD_HANDLERS')) for scheme, clspath in handlers.items(): self._schemes[scheme] = clspath self._load_handler(scheme, skip_lazy=True) crawler.signals.connect(self._close, signals.engine_stopped) def _get_handler(self, scheme): """Lazy-load the downloadhandler for a scheme only on the first request for that scheme. """ if scheme in self._handlers: return self._handlers[scheme] if scheme in self._notconfigured: return None if scheme not in self._schemes: self._notconfigured[scheme] = 'no handler available for that scheme' return None return self._load_handler(scheme) def _load_handler(self, scheme, skip_lazy=False): path = self._schemes[scheme] try: dhcls = load_object(path) if skip_lazy and getattr(dhcls, 'lazy', True): return None dh = create_instance( objcls=dhcls, settings=self._crawler.settings, crawler=self._crawler, ) except NotConfigured as ex: self._notconfigured[scheme] = str(ex) return None except Exception as ex: # ... else: self._handlers[scheme] = dh return dh def download_request(self, request, spider): scheme = urlparse_cached(request).scheme handler = self._get_handler(scheme) if not handler: raise NotSupported("Unsupported URL scheme '%s': %s" % (scheme, self._notconfigured[scheme])) return handler.download_request(request, spider) @defer.inlineCallbacks def _close(self, *_a, **_kw): # ...我们分别来解析这个类中定义的方法,都是非常重要的。此外,每个方法含义明确,而且代码精炼,我们对此一一进行说明。首先是 __init__() 方法,我们可以看到一个核心的语句:handlers = without_none_values(crawler.settings.getwithbase('DOWNLOAD_HANDLERS'))。其中 getwithbase() 方法的定义位于 scapy/settings/__init__.py 文件中,其内容如下:# 源码位置:scrapy/settings/__init__.py# ...class BaseSettings(MutableMapping): # ... def getwithbase(self, name): """Get a composition of a dictionary-like setting and its `_BASE` counterpart. :param name: name of the dictionary-like setting :type name: string """ compbs = BaseSettings() compbs.update(self[name + '_BASE']) compbs.update(self[name]) return compbs # ...从上面的代码中,可以知道 crawler.settings.getwithbase('DOWNLOAD_HANDLERS') 语句其实是获取了 settings.py 配置中的 DOWNLOAD_HANDLERS 和 DOWNLOAD_HANDLERS_BASE 值,并返回包含这两个属性值的 BaseSettings 实例。我们从默认的 scrapy/settings/default_settings.py 中可以看到这两个属性值如下:# 源码位置:scrapy/settings/default_settings.pyDOWNLOAD_HANDLERS = {}DOWNLOAD_HANDLERS_BASE = { 'data': 'scrapy.core.downloader.handlers.datauri.DataURIDownloadHandler', 'file': 'scrapy.core.downloader.handlers.file.FileDownloadHandler', 'http': 'scrapy.core.downloader.handlers.http.HTTPDownloadHandler', 'https': 'scrapy.core.downloader.handlers.http.HTTPDownloadHandler', 's3': 'scrapy.core.downloader.handlers.s3.S3DownloadHandler', 'ftp': 'scrapy.core.downloader.handlers.ftp.FTPDownloadHandler',}通常我们项目中的下载请求一般是 http 或者 https,对应的都是 scrapy.core.downloader.handlers.http.HTTPDownloadHandler 这个位置的 handler,从这里也可以看到 scrapy 框架其实是支持非常多协议下载的,比如 s3 下载、文件下载以及 ftp下载等。紧接着的两句就是在设置 self._schemes 和 self._handlers 的值。其中 self._handlers 会加载对应 Handler 类: def _load_handler(self, scheme, skip_lazy=False): # 获取协议对应的handler类路径,比如 ftp协议对应着的handler类为 # scrapy.core.downloader.handlers.ftp.FTPDownloadHandler path = self._schemes[scheme] try: # 获取相应的handler类,非字符串形式 dhcls = load_object(path) # 默认__init__()方法调用时参数skip_lazy为True,我们需要检查对应handler类中的lazy属性值,没有设置时默认为True;如果handler类中lazy属性设置为True或者不设置,则该handler不会加入到self._handlers中 if skip_lazy and getattr(dhcls, 'lazy', True): return None # 创建相应的handler类实例,需要的参数为: dh = create_instance( objcls=dhcls, settings=self._crawler.settings, crawler=self._crawler, ) except NotConfigured as ex: # ... except Exception as ex: # ... else: # 设置self._handlers self._handlers[scheme] = dh return dh上面的注释已经非常清楚,在众多 handlers 中,只有 S3DownloadHandler 类中没有设置 lazy。所以在 __init__() 方法执行完后,self._handlers 中不会有键 “s3” 及其对应的实例。_get_handler() 就非常明显了,由于我们在初始化方法 __init__() 中已经得到了 self._handlers,此时该方法就是根据传入的协议获取相应 Handler 类的实例。 例如传入的 scheme="http",则返回就是 HTTPDownloadHandler 类的一个实例。最后一个 download_request() 方法可以说是下载网页的核心调用方法。我们来逐步分析该方法中的语句:scheme = urlparse_cached(request).schemehandler = self._get_handler(scheme)上面两句是获取对应的下载请求的 Handler 实例,比较容易理解。接下来的 return 就是调用 handler 实例中的 download_request() 方法按照对应协议方式下载请求数据:return handler.download_request(request, spider)每个 handler 类都会有对应的 download_request() 方法。我们重点看看 http 和 https 协议对应的 handler 类:# 源码位置:scrapy/core/downloader/handlers/http.pyfrom scrapy.core.downloader.handlers.http10 import HTTP10DownloadHandlerfrom scrapy.core.downloader.handlers.http11 import ( HTTP11DownloadHandler as HTTPDownloadHandler,)可以看到,这里的 HTTPDownloadHandler 类实际上是 http11.py 中的 HTTP11DownloadHandler 类。这里面内容有点多,我们简要地分析下:# 源码位置:scrapy/core/downloader/handlers/http11.py# ...class HTTP11DownloadHandler: # ... def download_request(self, request, spider): """Return a deferred for the HTTP download""" agent = ScrapyAgent( contextFactory=self._contextFactory, pool=self._pool, maxsize=getattr(spider, 'download_maxsize', self._default_maxsize), warnsize=getattr(spider, 'download_warnsize', self._default_warnsize), fail_on_dataloss=self._fail_on_dataloss, crawler=self._crawler, ) return agent.download_request(request) # ...是不是挺简单的两条语句:得到 agent,然后调用 agent.download_request() 方法得到请求的结果?我们继续追踪这个 ScrapyAgent 类:# 源码位置:scrapy/core/downloader/handlers/http11.py# ...from twisted.web.client import Agent, HTTPConnectionPool, ResponseDone, ResponseFailed, URI# ...class ScrapyAgent: _Agent = Agent # ... def _get_agent(self, request, timeout): from twisted.internet import reactor bindaddress = request.meta.get('bindaddress') or self._bindAddress # 从请求的meta参数中获取proxy proxy = request.meta.get('proxy') if proxy: # 有代理的情况 # ... # 没有代理返回Agent的一个实例 return self._Agent( reactor=reactor, contextFactory=self._contextFactory, connectTimeout=timeout, bindAddress=bindaddress, pool=self._pool, ) def download_request(self, request): from twisted.internet import reactor # 从meta中获取下载超时时间 timeout = request.meta.get('download_timeout') or self._connectTimeout # 获取agent agent = self._get_agent(request, timeout) # request details url = urldefrag(request.url)[0] method = to_bytes(request.method) headers = TxHeaders(request.headers) if isinstance(agent, self._TunnelingAgent): headers.removeHeader(b'Proxy-Authorization') if request.body: bodyproducer = _RequestBodyProducer(request.body) else: bodyproducer = None start_time = time() # 使用agent发起请求 d = agent.request(method, to_bytes(url, encoding='ascii'), headers, bodyproducer) # set download latency d.addCallback(self._cb_latency, request, start_time) # response body is ready to be consumed d.addCallback(self._cb_bodyready, request) d.addCallback(self._cb_bodydone, request, url) # check download timeout self._timeout_cl = reactor.callLater(timeout, d.cancel) d.addBoth(self._cb_timeout, request, url, timeout) return d看完上面的代码就应该比较清楚了,我们先不考虑代理的相关代码。直接看 _get_agent() 方法就是获取 twisted 模块中 Agent 的一个实例,然后通过这个 agent 去请求网页 (在 download_request() 方法中完成 ),最后返回的仍然是一个 Deferred 对象。在 download_request() 中的代码就和我们在第一小节中介绍的类似,这里便是 Scrapy 最后完成网页抓取的地方,就是基于 Twisted 的 web client 部分的方法。其中,最核心的一行语句就是:d = agent.request(method, to_bytes(url, encoding='ascii'), headers, bodyproducer)这个分析已经走到了 Scrapy 下载器的最后一层,在往下就是研究 Twisted 框架的源码了。同学们有兴趣的话,可以继续追踪下去,对本节课而言,追踪到此已经结束了。我们跳出 handlers,继续研究 Downloader 类。
ready相关搜索
-
radio
radiobutton
radiobuttonlist
radiogroup
radio选中
radius
rails
raise
rand
random_shuffle
randomflip
random函数
rangevalidator
rarlinux
ratio
razor
react
react native
react native android
react native 中文