小米Note发布会

mikel阅读(977)

154432232507

小米的新品发布会更像是一场媒体会,国内不管是大小自媒体都在写关于小米的文章,观点不一,从价格争议到产品配置,还有小米的未来发展,写得淋漓尽致,让读者看得那叫一个迷茫。

为什么说迷茫呢?!因为小米的产品线实在太长了,不再是以前只做手机的小米了,又推去手环和小蚁运动相机,然后是雷军没否认的小米汽车,让米粉们频频爆料的各种产品,看上去很热闹,旁观的群众看得云里雾里,不清楚小米到底怎么了?!只能用迷茫概况了。

雷军的布局也许未来几年会可以解释,但是目前来说,能看懂的没几个,各种媒体都在猜测,然后就是各种自以为是的评判,所以说看着就好了,既然能出个小米模式,指不定未来又会折腾出个啥模式来。

2015年不管是小米这种号称互联网公司,还是自媒体,还是网民来说都将是不平静的一年,变革已经开始,但是最终是个什么结果,就看每个人如何把握这次移动互联网大潮了,微信火热得充当了导火索,每当有人跟我说发现一个好东西的时候,我就犯怵,因为这个世界太疯狂了,变化太坏了,出现得新东西和新模式都能以秒算,可真正能长久的也就BAT这几家,模式也很多,活下来的都是值钱的。看来时间真得能够验证一切。

从技术到产品的转型之路

mikel阅读(997)

 卢松松的博客看到一篇《我经历的哪些闷声发大财的行业》里面不少程序猿创业的故事,感觉程序猿除了走技术升级路线,还有很多选择,只能说世界是给又准备的人的,里面从2012年就开始专注微信的接口开发的到现在对微信功能和接口了解透彻,才能转行做培训,做营销方案,就像了解百度排名的算法得做SEO就轻车熟路一样。
psb作为互联网第一线的程序猿来说,很容易了解互联网的趋势和新产品,重要还在于选择,就像初学者选择开发语言一样。

重要还是在思维,很多人只在乎技术趋势,只要有新技术都第一时间学,然后使用,然后什么市场需求、营销充耳不闻,总觉得这些离自己很远,也许是人各有志,有些人喜欢钻研技术,有些人喜欢做产品吧。如果想从技术转型,最好思考技术背后的事情,以及产品的方向和趋势,这样就会把握好机会,先知先觉的把握核心的东西。

机器学习和计算机视觉相关的数学

mikel阅读(833)

.

机器学习

MIT一牛人对数学在机器学习中的作用给的评述,写得很实际

机器学习和计算机视觉都是很多种数学的交汇场。看着不同的理论体系的交汇,对于一个researcher来说,往往是非常exciting的enjoyable的事情。不过,这也代表着要充分了解这个领域并且取得有意义的进展是很艰苦的。

Linear Algebra (线性代数) 和 Statistics (统计学) 是最重要和不可缺少的。

这代表了Machine Learning中最主流的两大类方法的基础。一种是以研究函数和变换为重点的代数方法,比如Dimension reduction,feature extraction,Kernel等,一种是以研究统计模型和样本分布为重点的统计方法,比如Graphical model, Information theoretical models等。它们侧重虽有不同,但是常常是共同使用的,对于代数方法,往往需要统计上的解释,对于统计模型,其具体计算则需要代数的帮助。以代数和统 计为出发点,继续往深处走,我们会发现需要更多的数学。

Calculus (微积分),只是数学分析体系的基础。

其基础性作用不言而喻。Learning研究的大部分问题是在连续的度量空间进行的,无论代数还是统计,在研究优化问题的时候,对一个映射的微分或 者梯度的分析总是不可避免。而在统计学中,Marginalization和积分更是密不可分——不过,以解析形式把积分导出来的情况则不多见。

Partial Differential Equation (偏微分方程),这主要用于描述动态过程,或者仿动态过程。

这个学科在Vision中用得比Learning多,主要用于描述连续场的运动或者扩散过程。比如Level set, Optical flow都是这方面的典型例子。

Functional Analysis (泛函分析),通俗地,可以理解为微积分从有限维空间到无限维空间的拓展——当然了,它实际上远不止于此。
在这个地方,函数以及其所作用的对象之间存在的对偶关系扮演了非常重要的角色。Learning发展至今,也在向无限维延伸——从研究有限维向量的问题到 以无限维的函数为研究对象。Kernel Learning 和Gaussian Process 是其中典型的例子——其中的核心概念都是Kernel。很多做Learning的人把Kernel简单理解为Kernel trick的运用,这就把kernel的意义严重弱化了。在泛函里面,Kernel (Inner Product)是建立整个博大的代数体系的根本,从metric, transform到spectrum都根源于此。

Measure Theory (测度理论),这是和实分析关系非常密切的学科。但是测度理论并不限于此。

从某种意义上说,Real Analysis可以从Lebesgue Measure(勒贝格测度)推演,不过其实还有很多别的测度体系——概率本身就是一种测度。测度理论对于Learning的意义是根本的,现代统计学整 个就是建立在测度理论的基础之上——虽然初级的概率论教科书一般不这样引入。在看一些统计方面的文章的时候,你可能会发现,它们会把统计的公式改用测度来 表达,这样做有两个好处:所有的推导和结论不用分别给连续分布和离散分布各自写一遍了,这两种东西都可以用同一的测度形式表达:连续分布的积分基于 Lebesgue测度,离散分布的求和基于计数测度,而且还能推广到那种既不连续又不离散的分布中去(这种东西不是数学家的游戏,而是已经在实用的东西, 在Dirchlet Process或者Pitman-Yor Process里面会经常看到)。而且,即使是连续积分,如果不是在欧氏空间进行,而是在更一般的拓扑空间(比如微分流形或者变换群),那么传统的黎曼积 分(就是大学一年级在微积分课学的那种)就不work了,你可能需要它们的一些推广,比如Haar Measure或者Lebesgue-Stieltjes积分。

Topology(拓扑学),这是学术中很基础的学科。

它一般不直接提供方法,但是它的很多概念和定理是其它数学分支的基石。看很多别的数学的时候,你会经常接触这样一些概念:Open set / Closed set,set basis,Hausdauf, continuous function,metric space, Cauchy sequence, neighborhood, compactness, connectivity。很多这些也许在大学一年级就学习过一些,当时是基于极限的概念获得的。如果,看过拓扑学之后,对这些概念的认识会有根本性的拓 展。比如,连续函数,当时是由epison法定义的,就是无论取多小的正数epsilon,都存在xxx,使得xxx。这是需要一种metric去度量距 离的,在general topology里面,对于连续函数的定义连坐标和距离都不需要——如果一个映射使得开集的原像是开集,它就是连续的——至于开集是基于集合论定义的,不 是通常的开区间的意思。这只是最简单的例子。当然,我们研究learning也许不需要深究这些数学概念背后的公理体系,但是,打破原来定义的概念的局限 在很多问题上是必须的——尤其是当你研究的东西它不是在欧氏空间里面的时候——正交矩阵,变换群,流形,概率分布的空间,都属于此。

Differential Manifold (微分流形),通俗地说它研究的是平滑的曲面。

一个直接的印象是它是不是可以用来fitting一个surface什么的——当然这算是一种应用,但是这是非常初步的。本质上说,微分流形研究的 是平滑的拓扑结构。一个空间构成微分流形的基本要素是局部平滑:从拓扑学来理解,就是它的任意局部都同胚于欧氏空间,从解析的角度来看,就是相容的局部坐 标系统。当然,在全局上,它不要求和欧氏空间同胚。它除了可以用于刻画集合上的平滑曲面外,更重要的意义在于,它可以用于研究很多重要的集合。一个n-维 线性空间的全部k-维子空间(k

Lie Group Theory (李群论),一般意义的群论在Learning中被运用的不是很多,群论在Learning中用得较多的是它的一个重要方向Lie group。

定义在平滑流形上的群,并且其群运算是平滑的话,那么这就叫李群。因为Learning和编码不同,更多关注的是连续空间,因为Lie group在各种群中对于Learning特别重要。各种子空间,线性变换,非奇异矩阵都基于通常意义的矩阵乘法构成李群。在李群中的映射,变换,度量, 划分等等都对于Learning中代数方法的研究有重要指导意义。

Graph Theory(图论),图,由于它在表述各种关系的强大能力以及优雅的理论,高效的算法,越来越受到Learning领域的欢迎。
经典图论,在Learning中的一个最重要应用就是graphical models了,它被成功运用于分析统计网络的结构和规划统计推断的流程。Graphical model所取得的成功,图论可谓功不可没。在Vision里面,maxflow (graphcut)算法在图像分割,Stereo还有各种能量优化中也广受应用。另外一个重要的图论分支就是Algebraic graph theory (代数图论),主要运用于图的谱分析,著名的应用包括Normalized Cut和Spectral Clustering。近年来在semi-supervised learning中受到特别关注。

这是大牛们做的很好的综述啊!

[转载]大熊君大话NodeJS之------Global Objects全局对象 - 大熊君{{bb}} - 博客园

mikel阅读(1076)

[转载]大熊君大话NodeJS之——Global Objects全局对象 – 大熊君{{bb}} – 博客园.

一,开篇分析

 

在上个章节中我们学习了NodeJS的基础理论知识,对于这些理论知识来说理解是至关重要的,在后续的章节中,我们会对照着官方文档逐步学习里面的各部分模块,好了该是本文主角登台亮相的时候了,Global 

 

 

让我们来看一下官方的定义:

 

Global Objects全局对象

 

These objects are available in all modules. Some of these objects aren’t actually in the global scope but in the module scope – this will be noted.

 

这些对象在所有的模块中都可用。实际上有些对象并不在全局作用域范围中,但是在它的模块作用域中——这些会标识出来的。 

 

In browsers, the top-level scope is the global scope. That means that in browsers if you’re in the global scope var something will define a global variable.

 

In Node this is different. The top-level scope is not the global scope; var something inside a Node module will be local to that module.

 

全局对象这个概念我想大家应该不会感到陌生,在浏览器中,最高级别的作用域是Global Scope ,这意味着如果你在Global Scope中使用 “var” 定义一个变量,这个变量将会被定义成Global Scope。

 

但是在NodeJS里是不一样的,最高级别的Scope不是Global Scope,在一个Module里用 “var” 定义个变量,这个变量只是在这个Module的Scope 里。

 

在NodeJS中,在一个模块中定义的变量,函数或方法只在该模块中可用,但可以通过exports对象的使用将其传递到模块外部。

 

但是,在Node.js中,仍然存在一个全局作用域,即可以定义一些不需要通过任何模块的加载即可使用的变量、函数或类。

 

同时,也预先定义了一些全局方法及全局类Global对象就是NodeJS中的全局命名空间,任何全局变量,函数或对象都是该对象的一个属性值。

 

在REPL运行环境中,你可以通过如下语句来观察Global对象中的细节内容,见下图:

 

 

我在下面会逐一说说挂载在Global对象上的相关属性值对象。

 

 

 

(1),Process

 

process {Object} The process object.See the process  object section.

 

   process  {对象}  这是一个进程对象。 在后续的章节中我会细说,但在这里我要先拿出一个api来说一下。 

 

   process.nextTick(callback)

 

   On the next loop around the event loop call this callback. This is not a simple alias to setTimeout(fn, 0), it’s much more efficient. It typically runs before any other I/O events fire, but there are some       exceptions. See process.maxTickDepth below.

 

   在事件循环的下一次循环中调用 callback 回调函数。这不是 setTimeout(fn, 0) 函数的一个简单别名,因为它的效率高多了。

 

   该函数能在任何 I/O 事前之前调用我们的回调函数。如果你想要在对象创建之后而I/O 操作发生之前执行某些操作,那么这个函数对你而言就十分重要了。

 

   有很多人对Node.js里process.nextTick()的用法感到不理解,下面我们就来看一下process.nextTick()到底是什么,该如何使用。

 

 

 

   Node.js是单线程的,除了系统IO之外,在它的事件轮询过程中,同一时间只会处理一个事件。你可以把事件轮询想象成一个大的队列,在每个时间点上,系统只会处理一个事件。

 

   即使你的电脑有多个CPU核心,你也无法同时并行的处理多个事件。但也就是这种特性使得node.js适合处理I/O型的应用,不适合那种CPU运算型的应用。

 

   在每个I/O型的应用中,你只需要给每一个输入输出定义一个回调函数即可,他们会自动加入到事件轮询的处理队列里。

 

   当I/O操作完成后,这个回调函数会被触发。然后系统会继续处理其他的请求。

 

 

 

 

在这种处理模式下,process.nextTick()的意思就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行。我们来看一个例子。例子中有一个foo(),你想在下一个时间点上调用他,可以这么做:

 

1
2
3
4
5
6
function foo() {
    console.error('foo');
}
process.nextTick(foo);
console.error('bar');<br>  <br>  运行上面的代码,你从下面终端打印的信息会看到,"bar"的输出在“foo”的前面。这就验证了上面的说法,foo()是在下一个时间点运行的。

 

1
2
bar
foo

 

你也可以使用setTimeout()函数来达到貌似同样的执行效果:

 

1
2
setTimeout(foo, 0);
console.log('bar');

 

但在内部的处理机制上,process.nextTick()和setTimeout(fn, 0)是不同的,process.nextTick()不是一个单纯的延时,他有更多的 特性

 

更精确的说,process.nextTick()定义的调用会创建一个新的子堆栈。在当前的栈里,你可以执行任意多的操作。但一旦调用 netxTick,函数就必须返回到父堆栈。然后事件轮询机制又重新等待处理新的事件,如果发现nextTick的调用,就会创建一个新的栈。

 

下面我们来看看,什么情况下使用process.nextTick():

 

 

 

在多个事件里交叉执行CPU运算密集型的任务:

 

在下面的例子里有一个compute(),我们希望这个函数尽可能持续的执行,来进行一些运算密集的任务。

 

但与此同时,我们还希望系统不要被这个函数堵塞住,还需要能响应处理别的事件。这个应用模式就像一个单线程的web服务server。在这里我们就可以使用process.nextTick()来交叉执行compute()和正常的事件响应。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var http = require('http');
function compute() {
    // performs complicated calculations continuously
    // ...
    process.nextTick(compute);
}
http.createServer(function(req, res) {
     res.writeHead(200, {'Content-Type': 'text/plain'});
     res.end('Hello World');
}).listen(5000, '127.0.0.1');
compute();

 

在这种模式下,我们不需要递归的调用compute(),我们只需要在事件循环中使用process.nextTick()定义compute()在下一个时间点执行即可。

 

  在这个过程中,如果有新的http请求进来,事件循环机制会先处理新的请求,然后再调用compute()。

 

  反之,如果你把compute()放在一个递归调用里,那系统就会一直阻塞在compute()里,无法处理新的http请求了。你可以自己试试。

 

  当然,我们无法通过process.nextTick()来获得多CPU下并行执行的真正好处,这只是模拟同一个应用在CPU上分段执行而已。

 

 

 

  (2),Console

 

  console {Object} Used to print to stdout and stderr.See the stdio section. 

 

  控制台 {对象} 用于打印到标准输出和错误输出。看如下测试:

 

  

 

1 console.log("Hello Bigbear !") ;
2 for(var i in console){
3     console.log(i+"  "+console[i]) ;
4 }

 

 

 

会得到以下输出结果:

 

 

复制代码
 1 var log = function () {
 2   process.stdout.write(format.apply(this, arguments) + '\n');
 3 }
 4 var info = function () {
 5   process.stdout.write(format.apply(this, arguments) + '\n');
 6 }
 7 var warn = function () {
 8   writeError(format.apply(this, arguments) + '\n');
 9 }
10 var error = function () {
11   writeError(format.apply(this, arguments) + '\n');
12 }
13 var dir = function (object) {
14   var util = require('util');
15   process.stdout.write(util.inspect(object) + '\n');
16 }
17 var time = function (label) {
18   times[label] = Date.now();
19 }
20 var timeEnd = function (label) {
21   var duration = Date.now() - times[label];
22   exports.log('undefined: NaNms', label, duration);
23 }
24 var trace = function (label) {
25   // TODO probably can to do this better with V8's debug object once that is
26   // exposed.
27   var err = new Error;
28   err.name = 'Trace';
29   err.message = label || '';
30   Error.captureStackTrace(err, arguments.callee);
31   console.error(err.stack);
32 }
33 var assert = function (expression) {
34   if (!expression) {
35     var arr = Array.prototype.slice.call(arguments, 1);
36     require('assert').ok(false, format.apply(this, arr));
37   }
38 }
复制代码

 

通过这些函数,我们基本上知道NodeJS在全局作用域添加了些什么内容,其实Console对象上的相关api只是对Process对象上的”stdout.write“进行了更高级的封装挂在到了全局对象上。

 

 

 

(3),exports与module.exports

 

在NodeJS中,有两种作用域,分为全局作用域和模块作用域

 

复制代码
var name = 'var-name';
name = 'name';
global.name='global-name';
this.name = 'module-name';
console.log(global.name);
console.log(this.name);
console.log(name);
复制代码

 

我们看到 var name = ‘var-name’;name = ‘name’;  是定义的局部变量;

 

而 global.name=’global-name’; 是为 全局对象定义一个name 属性,

 

而 this.name = ‘module-name’; 是为模块对象定义了一个name 属性

 

那么我们来验证一下,将下面保存成test2.js,运行

 

 

var t1 = require('./test1');  
console.log(t1.name);  
console.log(global.name);  

 

从结果可以看出,我们成功导入 了test1 模块,并运行了 test1的代码,因为在test2 中 输出 了 global.name,

 

而 t1.name 则是 test1 模块中通过 this.name 定义的,说明this 指向 的是 模块作用域对象。

 

exports与module.exports的一点区别

 

    Module.exports才是真正的接口,exports只不过是它的一个辅助工具。最终返回给调用的是Module.exports而不是exports。

 

    所有的exports收集到的属性和方法,都赋值给了Module.exports。当然,这有个前提,就是Module.exports本身不具备任何属性和方法

 

    如果,Module.exports已经具备一些属性和方法,那么exports收集来的信息将被忽略。

 

  举个栗子:

 

    新建一个文件 bb.js

 

exports.name = function() {
    console.log('My name is 大熊 !') ;
} ;

 

创建一个测试文件 test.js

 

 

var bb= require('./bb.js');
bb.name(); // 'My name is 大熊 !'

 

修改bb.js如下:

 

module.exports = 'BigBear!' ;
exports.name = function() {
    console.log('My name is 大熊 !') ;
} ;

 

再次引用执行bb.js

 

var bb= require('./bb.js');
bb.name(); // has no method 'name'

 

由此可知,你的模块并不一定非得返回“实例化对象”。你的模块可以是任何合法的JavaScript对象–boolean, number, date, JSON, string, function, array等等。

 

 

 

(4),setTimeout,setInterval,process.nextTick,setImmediate

 

  以下以总结的形式出现

 

    Nodejs的特点是事件驱动,异步I/O产生的高并发, 产生此特点的引擎是事件循环,事件被分门别类地归到对应的事件观察者上,比如idle观察者,定时器观察者,I/O观察者等等,事件循环每次循环称为 Tick,每次Tick按照先后顺序从事件观察者中取出事件进行处理。

 

     调用setTimeout()或setInterval()时创建的计时器会被放入定时器观察者内部的红黑树中,每次Tick时,会从该红黑树中检 查定时器是否超过定时时间,超过的话,就立即执行对应的回调函数。setTimeout()和setInterval()都是当定时器使用,他们的区别在 于后者是重复触发,而且由于时间设的过短会造成前一次触发后的处理刚完成后一次就紧接着触发。

 

     由于定时器是超时触发,这会导致触发精确度降低,比如用setTimeout设定的超时时间是5秒,当事件循环在第4秒循到了一个任务,它的执行时 间3秒的话,那么setTimeout的回调函数就会过期2秒执行,这就是造成精度降低的原因。并且由于采用红黑树和迭代的方式保存定时器和判断触发,较 为浪费性能。

 

     使用process.nextTick()所设置的所有回调函数都会放置在数组中,会在下一次Tick时所有的都立即被执行,该操作较为轻量,时间精度高。

 

     setImmediate()设置的回调函数也是在下一次Tick时被调用,其和process.nextTick()的区别在于两点:

 

1,他们所属的观察者被执行的优先级不一样,process.nextTick()属于idle观察者,setImmediate()属于check观察者,idle的优先级>check。

 

       2,setImmediate()设置的回调函数是放置在一个链表中,每次Tick只执行链表中的一个回调。这是为了保证每次Tick都能快速地被执行。

 

 

 

 

 

二,总结一下

 

  1,理解Global对象存在的意义

 

  2,exports与module.exports的一点区别

 

  3,Console的底层是什么构建的(Process对象的高层封装)

 

  4,setTimeout,setInterval,process.nextTick,setImmediate的区别

  5,NodeJS中的两种作用域

[转载]大熊君大话NodeJS之开篇------Why NodeJS(将Javascript进行到底) - 大熊君{{bb}} - 博客园

mikel阅读(1100)

[转载]大熊君大话NodeJS之开篇——Why NodeJS(将Javascript进行到底) – 大熊君{{bb}} – 博客园.

一,开篇分析

大家好啊,大熊君又来啦(*^__^*) 嘻嘻……,之前我写过一系列关于JS(OOP与设计模式)方面的文章,反响还好,其实这也是对我本人最大的鼓励,于是我决定我要将JavaScript进行到底

准备写一个NodeJS方面的系列文章,由浅入深,循序渐进,秉承的理念是重思想,多实践,勤能补拙,贵在坚持。

我们先来看看NodeJS官网上的介绍:

其特点为:

1,它是一个JavaScript运行环境

  2,依赖于Chrome V8引擎进行代码解释

  3,事件驱动

  4, 非阻塞I/O

  5, 轻量、可伸缩,适于实时数据交互应用

  6,单进程,单线程

  

  (1),Nodejs为什么选择JavaScript为载体语言

    事实上,在实现 Node.js 之初,作者 Ryan Dahl 并没有选择 JavaScript,他尝试过 C、Lua,皆因其欠缺一些高级语言的特性,如闭包、函数式编程,致使程序复杂,难以维护。

    而 JavaScript 则是支持函数式编程范型的语言,很好地契合了 Node.js 基于事件驱动的编程模型。加之 Google 提供的 V8 引擎,使 JavaScript 语言的执行速度大大提高。

    最终呈现在我们面前的就成了 Node.js,而不是 Node.c,Node.lua 或其他语言的实现。

 

  (2),Node.js不是JS应用、而是JS运行平台

    看到Node.js这个名字,初学者可能会误以为这是一个Javascript应用,事实上,Node.js采用C++语言编写而成,是一个Javascript的运行环境。

    Node.js采用了Google Chrome浏览器的V8引擎,性能很好,同时还提供了很多系统级的API,如文件操作、网络编程等。

    以下是NodeJS所涉及的全部模块:

    

    浏览器端的Javascript代码在运行时会受到各种安全性的限制,对客户系统的操作有限。

    相比之下,Node.js则是一个全面的后台运行时,为Javascript提供了其他语言能够实现的许多功能。

 

  (3),Node.js的特点

    Node.js在设计上也是比较创新,它以单进程,单线程模式运行(这和Javascript的运行方式是一致的),

    事件驱动机制是Node.js通过内部单线程高效率地维护事件循环队列来实现的,没有多线程的资源占用和上下文切换,这意味着面对大规模的http请求,Node.js凭借事件驱动搞定一切,

    习惯了传统语言的网络服务开发人员可能对多线程并发和协作非常熟悉,但是面对Node.js,我们需要接受和理解它的特点。

 

 

 

二,重要概念

1,什么是 Event Loop ?(很重要的概念)

    Event Loop 是一个很重要的概念,指的是计算机系统的一种运行机制。

    想要理解Event Loop,就要从程序的运行模式讲起。运行以后的程序叫做进程(Process),一般情况下,一个进程一次只能执行一个任务。

    如果有很多任务需要执行,不外乎三种解决方法。

      (1),排队。因为一个进程一次只能执行一个任务,只好等前面的任务执行完了,再执行后面的任务。

      (2),新建进程。使用fork命令,为每个任务新建一个进程。

      (3),新建线程。因为进程太耗费资源,所以如今的程序往往允许一个进程包含多个线程,由线程去完成任务。

    以JavaScript语言为例,它是一种单线程语言,所有任务都在一个线程上完成,即采用上面的第一种方法。一旦遇到大量任务或者遇到一个耗时的任务,网页就会出现”假死”,因为JavaScript停不下来,也就无法响应用户的行为。

    你也许会问,JavaScript为什么是单线程,难道不能实现为多线程吗?

    这跟历史有关系:

      JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。

      JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。

      比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

      所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

      为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。
      所以,这个新标准并没有改变JavaScript单线程的本质。

      回到EventLoop:

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。

JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,

才能执行后一个任务;异步任务指的是,不进入主线程、而进入”任务队列”(task queue)的任务,只有”任务队列”通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

如下图:

只要主线程空了,就会去读取”任务队列”,这就是JavaScript的运行机制。这个过程会不断重复。

三,实例讲解

好了,“废话”不多说了,马上开始我们第一个NodeJS应用:“Hello 大熊”。

打开你最喜欢的编辑器,创建一个HelloWorld.js文件。

代码如下:

复制代码
1 var http = require("http") ;
2 http.createServer(function(request,response){
3     response.writeHead(200,{
4         "Content-Type" : "text/plain"
5     }) ;
6     response.write("Hello,大熊 !") ;
7     response.end() ;
8 }).listen(8888) ;
复制代码

我们来运行并且测试这段代码。首先,用Node.js执行你的脚本:

打开命令行工具CMD,切换到你的工作目录,运行命令“node HelloWorld.js”

接下来,打开浏览器访问 http://localhost:8888/ ,你会看到一个写着 “Hello,大熊 !” 的网页。

一点小的扩展知识:

如下图所示,这是NodeJS中的http.js部分源码,createServer是一个对用户很友好的接口,内部实现采用了单例模式,这样做的好处是,把实例的创建和初始化任务进行有效的分离,职责专一,降低耦合度,这是大家平时编程时可以借鉴的思想。

哈哈哈,是不是很有意思,这只是一次短暂的体验,后面会陆续讲解很多的知识点,大家慢慢体会O(∩_∩)O哈哈~

四,总体概述

  1,它是一个Javascript运行环境

  2,依赖于Chrome V8引擎进行代码解释

  3,事件驱动

  4, 非阻塞I/O

  5, 轻量、可伸缩,适于实时数据交互应用

  6,单进程,单线程

  最后我想说的话是:这篇的例子不是很多,但是这些概念相当重要,一定要有一个清晰的理解,这样为以后的NodeJS学习会打下牢固的基础的,朋友们加油一起努力。

 

2014年,那些“颜值”爆表的UI动画

mikel阅读(1106)

.

一款应用能否吸引更多的用户,并不仅仅只取决于它的功能是否强大。要知道,在这个看脸的世界里,即使你是App,也别想逃脱这个思维圈。拥有良好用户体验的UI,是让用户继续使用应用的潜在推动力。这里,我们挑选了2014年,在UI动画方面做得非常不错的几款应用,从他们的成功之处,捕捉自己所需的设计灵感。

1. Design Shots

对于Dribbble,相信很多设计师并不陌生,那里汇集了众多国内外的设计者,他们在Dribbble上面发布优秀的设计作品,包括UI、图标、 交互等,是获取灵感的不二之选。不过,早期在手机上浏览Dribbble却不是件愉快的体验,不能实现关注、点赞等操作,只能是纯粹的浏览。好在有了采用 全新Dribbble API的Design Shots,一个没有过度设计的Dribbble客户端。

不过,既然是为设计师准备的应用,即使走的是主流设计的简约路线,但是整体的感觉依旧是逼格满满。尤其是动画,绝对是了不起的。Design Shots减少了很多不必要的过场动画,精简下来的 每个动画和其他之间的切换都是那么的浑然天成,根本就不会给人将多个动画库揉在一起的感觉。Design Shots的动画始终在跟随着你的手指,你的每一个触动都会带来细微的不同。

2. Lush

Lush 应用相当于是一部鸡尾酒的词典,里面包括众多鸡尾酒的种类和配方,用各种不同的颜色来代表每一种基础配方,用藏青色来代表普通朗姆酒,用淡绿色代表淡朗 姆,用新绿色代表柠檬汽水,用蓝色代表琴酒等。而且,Lush中的动画也是不输任何应用的,隔着屏幕对鸡尾酒的浏览就像在看一部西部老电影一样,代表不同 鸡尾酒的混合染色出现在各种类型的酒杯中,还伴随着来回的晃动,脱俗的界面设计,让挑选和认识鸡尾酒的过程变成一种乐趣和时尚。

3. Clima

如 果说Design Shots走的是简约派,那么Clima的路线绝对是小萝莉,应用里充满了可爱的动画。主界面由上而下是由暖色逐步过渡到冷色,应用内界面切换细节不仅流 畅自然还伴随着顽皮的弹性效果。当获取温度时,颜色条框上还会出现萌萌的涟漪动画。任意方向的滑动都会激活一项任务,在App Store众多的天气应用中,轻量级的Clima能够立足其中,充满活力的动画效果是不可或缺的存在。如果你在做一款比较大众的应用的话,通过动画效果将 应用变得更有意思会是你胜过其他对手的一个不错的方式。

4. Storehouse

作 为获得2014年苹果设计奖的应用,Storehouse肯定有其过人之处。它是一款通过图片和视频组成的社交软件,最大的亮点就是无边框的界面设计,让 你打开应用就像翻阅一本杂志一样,随意而又简洁。当你浏览社区中他人发布的故事或自己发布的故事时,视频可以使用缩略图的形式播放,无需点击进入就可明白 大致的内容。当然,作为一个能够讲述故事的应用,它最吸引的地方就是精致的动画和排版,打开或关闭,只需随意滑动或缩放,这些都会让你不自觉的深陷其中, 寻找来自世界各地的平凡人的美好事物。

5. ReadMe

ReadMe.io 以一只呆萌的猫头鹰作为指导员,当你进行注册或登录操作时,它会在边上做个简单的指引。在注册页面,猫头鹰的右翅膀会指向你要填写的字段,当你的完成填 写,进入下一个时,小翅膀的方向也会随之转移;而在登录页面时,猫头鹰的眼睛焦点定在填写邮箱地址处,等到填写密码时,它会自动捂住自己的双眼。别以为这 只是很简单的动画效果,但却是取悦用户的完美例子。单调的填写信息的页面总会让人不耐烦,不妨加入一些鲜明的动画效果,让它们不再枯燥无味。

6. Unread

Unread 是iOS上的一款RSS阅读器,起初是由独立开发者Jared Sinclair完成,之后被Supertop开发商购买并进行后续开发。相较于其他阅读器,Unread要更纯粹精简一点,UI界面不会有其他干扰元 素。它拥有极好的手势和动画效果,整个应用采用的都是手势交互,刚开始可能有点不习惯,不过时间一长你会发现其中的便捷性。此外,最受喜欢的是流畅的下拉 刷新动画,让阅读成为一种享受,也让Unread变得更有质感。

7. TodoMovies

TodoMovies 是一款用来发现和管理新电影的应用,对于那些电影爱好者来说,它的出现让你对影片的信息手到擒来。TodoMovies应用制作精良,里面涵盖各种你所需 要的电影信息,无论是上映时间、电影简介还是预告片。不过,说到UI动画,值得一提的是点击分享后,TodoMovies会将电影海报缩小并进行圆形化处 理,几种分享方式会出现在缩略图上下左右,相较原生分享方式要更炫酷一点。小小的一个改变,却大大的提升了用户体验。

最后值得一提的Google Inbox


Inbox是Google发布的一款全新的邮箱应用,与Gmail同步后,会根据功能和来源对邮件进行细致的分类,让收件箱不再杂乱不堪。此外,还兼顾设置待办事项和设定邮件的处理日期等功能。当然,最令人眼前一亮的还是它的界面设计,使用全新设计语言Material Design打造的Inbox,有着很强的动画感,图标的滑出和板块的划分无不在昭示着Inbox的现代化。不过,Gmail的这次大整容,我们是无福消受了。

文章来源:Beautiful Pixels (可进入查看视频演示)

开源的世界

mikel阅读(1185)

 月光博客的一篇《开源之死》道尽了开源世界的辛酸,其实不是开源死了,是人心涣散,开源导致版本泛滥,看看现在的Android系统就知道了,不过个人觉得开源利大于弊,不开放永远都无法进步,微软不开源的主导者,不过最近也在想开源靠拢,大势所趋,大家都开源了,你还死守着不放,只能被群众抛弃。

互联网上很多项目都是开源的,很多人说开源的项目太烂,其实是你只懂得获取,不懂得付出,烂不怕为什么你不优化修改后发布出来,造福大家?!这就是喊着要开源的口号,赚着开源的钱的人的心态。

又回到媒体圈,同样的问题,大家都在那盯着别家的文章,采集过来,改改然后发布,赚人气,又有多少是自己深入写得,为什么说传统媒体穷途末路了,就是因为缺乏开源奉献的精神,自媒体革他们的命,也是必然的,自媒体为什么这么火爆,就是因为这帮自媒体人不计报酬,无私的在开源的为互联网贡献着信息,就是这么可爱的一帮人没想怎么地,就把传统媒体给推翻了。

开源如果只当个噱头,那不如不开源,最起码不会让世界乌烟瘴气,如果没有分享贡献精神,那就不叫开源,那叫抄袭。

[转载]Google 域名的秘密 - 7k - 博客园

mikel阅读(929)

[转载]Google 域名的秘密 – 7k – 博客园.

声明:本文采用 BY-NC-SA 协议进行授权。 转载请注明转自:Google 域名的秘密

哈哈,我也标题党一回。

其实也不算是秘密,只能说是我在制作 https://github.com/lennylxx/ipv6-hosts 时总结的规律。

Google 是世界上最大的互联网公司,其庞大的规模体现在各个方面。其中一面即是其规模宏大的全球网络,以及难以计数的服务器。有人估计 Google 在 2013 年初的时候大概有 238 万台服务器。

Google 在全球建造了 13 个数据中心,通过其自己组建的多层内容分发网络(CDN),为全球超过 100 多个国家的用户提供免费内容及服务。

data_center本文主要简要介绍一下 Google IPv6 地址与相关的域名。

Google (AS15169) IPv6 地址分配

2001:4860:4000::/36 United States
2404:6800:4000::/36 Australia
2607:f8b0:4000::/36 United States
2800:03f0:4000::/36 Argentina
2a00:1450:4000::/36 Ireland
2c0f:fb50:4000::/36 Kenya

可以看到,Google 在全球各大洲几乎都申请了 IP 段,为其 CDN 服务。

其中亚洲和大洋洲 IP 段注册国为澳大利亚,北美洲注册国为美国,欧洲注册国为爱尔兰,南美注册国为阿根廷,非洲则为肯尼亚。

Google IP 段的管理方式

下面以 2607:f8b0:4000::/36 为例简要介绍一下 Google IP 段的管理方式。

这个 IP 段的掩码有 36 位,因此理论上,这个 IP 段可用地址数为 2 ^ 92,约 4.95e27 个。

如此庞大的 IP 数量当然用不完,也需要一个比较好的管理方式。

Google 主要用了服务器部署位置附近的机场的 IATA 编码 来为服务器分组。IATA 编码为 3 位英文字母,用来唯一标识一个国际机场。比如北京首都国际机场的编码为 PEK,香港国际机场的编码为 HKG 等等。

其 IPv6 各段代表的含义如下:

  1. 33-48 位 (共 16 位) 表示城市编号,如 4000 代表达拉斯,4007 代表洛杉矶,400a 代表西雅图等等。
    (需要注意的是,由于 Google 所有的 IP 段都有 36 位掩码,因此所有的城市编号都是以4 开头的。)
  2. 49-64 位 (共 16 位) 则分成 5 段,每段使用方式不同,具体见下表格。
    49-64 位 用途
    0-3ff sn [20]/[6]
    400-7ff sn [8]
    800-bff iata 1e100.net
    c00-fff xx 1e100.net
    remaining unknown

    如表格所示:

    • 0-3ff 地址段用于 sn 编码域名,每组地址 20 个或 6 个。
      如在 4007 洛杉矶(LAX),1b 对应编码 a5m7lner
      (域可以是*.googlevideo.com *.gvt1.com*.c.youtube.com*.c.docs.google.com *.c.Android.clients.google.com。)
    • 400-3ff 地址段也用于 sn 编码域名,每组地址则为 8 个。
      如在洛杉矶,402 对应编码 a5m7zu7s
    • 800-bff 地址段用于 1e100.net 域名的 IATA 编码地址,每组地址 32 个。
      如在 4002 亚特兰大(ATL),802 对应编码 atl14s08
    • c00-fff 地址段用于 1e100.net 域名的两位字母编码地址,每组地址 256 个。
      如在亚特兰大,c01 对应编码 yh

    sn 编码域名和 1e100.net 域名的详细信息参见维基页面 sn 编码域名Youtube1e100.net

  3. 65-112 位 (共 48 位) 均为 0。
  4. 113-128 位 (共 16 位) 表示服务器编号,对应独立二级域名,具体规则请查看 hosts 文件。

上面的四条规则是不是看得晕头转向?

举个栗子:

比如 dfw06s16-in-x1f.1e100.net这个域名,这是一个典型的 1e100.net 域名,其对应的 IPv6 地址为 2607:f8b0:4000:800::101f

  • dfw 是 IATA 编码,代表“达拉斯-沃思堡国际机场”,也就是达拉斯市,这是美国德克萨斯州东北部的一个城市,前段时间的一部电影《达拉斯买家俱乐部》中的故事就是发生在这里。(好像扯远了
  • IPv6 第3段为 4000,对应的即是达拉斯市。
  • -in- 之后有个字母 x,表示其后两位编号是16进制,取值范围 0x00-0x1f,共32台。
  • IPv6 第4段地址取值范围 800-80f,共16组服务器,但各地数量不同,地址池并未完全使用。
  • IPv6 地址的末尾(第8段) 则是从1000到101f,和域名编号相对应。

再比如 r1---sn-o097znl7.googlevideo.com 这个域名,这是一个 sn 编码域名,其对应的 IPv6 地址为 2607:f8b0:4005:4::6

  • o09 是 IATA 编码的转换形式,通过对整个 8 位 sn 编码进行逆转换,可以得到nuq04s20,这个编码就和上面那个例子中的 1e100.net 域名编码类似了。其中nuq 代表“墨菲特联邦机场”,位于美国加州山景城市的南部,而山景城正是 Google 总部的所在地,查看地图你就可以知道这个机场就在 Google 总部的隔壁。
  • IPv6 第3段为 4005,对应的即是山景城市。
  • IPv6 地址的末尾(第8段) 则是从6到19,共 20 个,和域名编号(r1)相对应。

关于如何将 sn 编码进行逆转换,得到 IATA 编码地址,可以参考这个维基页面 https://github.com/lennylxx/ipv6-hosts/wiki/sn-domains

如果你想了解更多,可以查阅维基 https://github.com/lennylxx/ipv6-hosts/wiki,并欢迎提出修改意见。

你还可以查看完整的 1e100 服务器分配表格sn 编码域名表格。(需要科学上网)

[转载]ECSHOP的缓存问题_逍遥山庄_新浪博客

mikel阅读(994)

[转载]ECSHOP的缓存问题_逍遥山庄_新浪博客.

ECSHOP的缓存存放在templates/caches/文章夹下,时间长了这个文件夹就会非常庞大,拖慢网站速度。还有很多情况我们不需要他的缓存。本文介绍禁用ECSHOP缓存的方法。

ECSHOP的缓存有两部分,一部分是SMARTY的页面缓存;另一部分是SQL查询结果的缓存。这两部分都是保存在 templates/caches/文件夹下。只要我们分别关闭这两个功能,就可以完全禁用ECSHOP的缓存。当然你也可以根据自己的需要关闭其中某一个。

1.关闭SMARTY的缓存:
打开includes/cls_template.php,找到下面一段

if (file_put_contents($this->cache_dir . ‘/’ . $cachename . ‘.php’, ‘<?php exit;?>’ . $data . $out) === false)
      {
          trigger_error(’can\’t write:’ . $this->cache_dir . ‘/’ . $cachename . ‘.php’);
      }

将这一部分注释掉即可,改成

2.关闭SQL查询结果缓存 PHP之家
打开includes/cls_mysql.php
找到
var $max_cache_time=3600;//最大的缓存时间,以秒为单位
改为
var $max_cache_time=0;//最大的缓存时间,以秒为单位

--------------------------------------------

如何限制或禁用ECShop缓存呢?按道理只要ftp登录到主机空间服务器,清除“templates/caches”文件夹下的缓存文件,但比较安全稳妥的办法是进入ecshop网店后台点击右上角“清除缓存”按钮。还是完全禁用ecshop的缓存功能。

一、禁用ecshop部分数据表缓存
ecshop 里caches文件夹缓存文件包括sql查询结果缓存和SMARTY模板页面缓存。如果访问网站的用户一多,这些临时的缓存数据都被保持在ECshop的 “templates/caches”文件夹下。数据缓存对提高网店速度有一定作用,但缓存文件一多也就过犹不及。有人说只对 favourable_activity,goods_activity这2个表禁用缓存即可。
打开include/init.php,找到

PHP代码
  1.     
  2. $db->set_disable_cache_tables(array($ecs->table(’sessions’),$ecs->table(’sessions_data’),$ecs->table(’cart’)));   

修改为

PHP代码
  1.     
  2. $db->set_disable_cache_tables(array($ecs->table(’sessions’),$ecs->table(’sessions_data’),$ecs->table(’cart’),$ecs->table(’favourable_activity’),$ecs->table(’goods_activity’)));  

二、完全禁用ecshop缓存
定期要登录ecshop网店后台清除缓存文件,对于懒人来说,这也挺嫌麻烦的。那干脆完全禁用ecshop缓存吧。参考小虫的禁用echsop缓存文章,小虫的具体代码是2.6.0左右的版本。2.7的ecshop禁用缓存修改方法类似:

1. 用editplus打开include/cls_template.php,把下面代码注释掉:

PHP代码
  1.     
  2.   

2.用editplus打开include/cls_mysql.php,找到 max_cache_time = 300,把300改为0即可

三、templates/compiled下的文件是否可以清空?
templates/compiled下的文件是模板编译后文件,可以清空。当用户浏览网店后又会重新生成。templates文件夹下的主要是 caches里缓存文件太多,你可以定期清空或完全禁用ecshop缓存。

----------------------------------------------

关于清除缓存的建议!!  PHP之家

发现现在的清除缓存做的比较粗!和之前没大变化啊!和2.0.5一样.
只要后台随便一个修改的操作,整个缓存就都没了!用的都是$smarty->clear_all_cache();
缺点:如果我有10万商品,:),而且都被浏览过,我后台一个操作就要清楚15万多缓存文件:)似乎极限了点
只是举例!!,希望ECSHOP更加完美而已!

smarty里面不是有这个函数么?
clear_cache(),我小修改了下,增加了可以指定删除某个目录下的缓存,用处是:可方便的删除商品的分类缓存!

2.0.5上我是这么改的,另外在根目录建立一个缓存目录templates_caches,里面建立 article,article_cat,goods,goods_cat,4个文件夹分别放文章内容,文章列表,商品内容,商品列表的缓存
例子:对商品,文章部分的修改
前台init.php和后台init.php加入如下代码,我为了方便直接加在config.php里面了

  1. //缓存目录设置   PHP之家
  2. define(‘ECS_ROOT’, substr(dirname(__FILE__), 0, -8));//前后台数字当然不一样了:)
  3. //文章缓存
  4. $cache_dir_article = ECS_ROOT.’./templates_caches/article’;
  5. $cache_dir_article_cat = ECS_ROOT.’./templates_caches/article_cat’;
  6. //商品缓存
  7. $cache_dir_goods = ECS_ROOT.’./templates_caches/goods’;
  8. $cache_dir_goods_cat = ECS_ROOT.’./templates_caches/goods_cat’;

复制代码

前台商品内容和分类缓存时间单独设置长一些,如内容一个月,分类1天
修改后台,商品单独修改的地方只删除这个商品内容的缓存
只要有修改操作就删除商品分类缓存和首页缓存!加入如下
$smarty->clear_cache(null, null, null, null, $cache_dir_goods_cat);//zouql:删除商品目录缓存,默认缓存时间
$smarty->clear_cache(‘goods.html’, $goods_id, null, null, $cache_dir_goods);//zouql:删除商品缓存,默认缓存时间
还有广告管理等等等等等等等等地方要改!
前台用户发表评论后自动删除本商品缓存等等……….
PHP之家

function clear_cache($tpl_file = null, $cache_id = null, $compile_id = null, $exp_time = null, $cache_dir = null)
{

     if (!isset($cache_dir))
$cache_dir = $this->cache_dir;

if (!isset($compile_id))
        $compile_id = $this->compile_id;

      if (!isset($tpl_file))
        $compile_id = null;

      $_auto_id = $this->_get_auto_id($cache_id, $compile_id);

      if (!empty($this->cache_handler_func)) {
        return call_user_func_array($this->cache_handler_func,
                             array(‘clear’, &$this, &$dummy, $tpl_file, $cache_id, $compile_id, $exp_time));
      } else {
        $_params = array(‘auto_base’ => $cache_dir,
                       ‘auto_source’ => $tpl_file,
                       ‘auto_id’ => $_auto_id,
                       ‘exp_time’ => $exp_time);
        require_once(SMARTY_CORE_DIR . ‘core.rm_auto.php’);
        return smarty_core_rm_auto($_params, $this);
      }

}

---------------------------------------------

定期清除缓存页面插件 PHP之家

软件类型:国产软件 授权方式:共享软件 界面语言:简体中文 软件大小:未知 文件类型:.rar 运行环境:Win2003,WinXP,Win2000,Win9X 软件等级:&#9733;&#9733;&#9733;&#9733;&#9733; 发布时间:2009-08-26 官方网址:http:// 演示网址:http:// 下载次数: 47
ecshop缓存清理-限制或禁用ECShop缓存 PHP之家 - 云帆 - 云帆
软件介绍 PHP之家

利用ECSHOP的计划与任务清除过多的缓存页面文件
重要说明:
1.适用于utf-8编码;
2.原下载包内languages的路径有错误,正确的是:languages\zh_cn \cron\myclr.php

大家快出来列队欢迎 wutao0808 ,
wutao0808 的文件经测试 没有问题,不会破坏系统
我在此贴中做个备份,下面第一个为楼主的文件,清楚缓存,但不清除模板的编译   直接复制到商城的根目录下即可

下面的这个文件是我稍做修改 其中做了注释 ,默认为清除全部文件(包括缓存和模板编译 ),如果只需清楚缓存文件,注释掉

clear_all_files(); 改为 //clear_all_files();

将清除缓存的取消注释 //clear_cache_files(); 改为

  //clear_cache_files(); 即可

微商要分工才能有赚头儿

mikel阅读(1203)

现在的微商属于“奶妈阶段”,啥叫奶妈阶段?就是从进货,到销售推广再到售后客服还有配送都是一个人在弄,面面俱到,哪个环节不注意就是麻烦,结果一个人分身乏术,忙得不亦乐乎还赚不到钱,毕竟作微商的个人居多,也有团队的,就是一个团队各司其职,然后组团开卖,可是指着一两个人又能在微商海洋里溅起多大的浪花儿,可想而知。

微商应该升级到“托儿所阶段”,就是让供货得踏踏实实的供货,推广卖货的只需要卖货,然后 人少的问题就别指望刷朋友圈了,直接对接大的微信服务号提供的平台,人家已经有十好几万的关注量,还怕人少没人买?
所以说,组团做微商已经过时了,现在要分工协作做才有出路,2015年将迎来微商大清洗的一年,就像互联网时代的淘宝网初期,开始人人开店,结果是组团运营,最后是淘宝客助阵才来得繁荣。微商也将是一个这么过程。

未来移动互联网电商会更加普及,电商也将步入移动电商时代,微商只是试水,大家都在摸索中前进,但想要做大只能专注,让大家分工明确,上下游各尽其职,然后合作共赢才是最终的微商之道。