来源 | 《区块链+ 开启智能新时代》
作者 | 张元林、陈序、赵熙
责编 | 乔治
出品 | 区块链大本营(blockchain_camp)
##文末送书啦啦啦
你通过微信、微博、今日头条等维护人际关系、了解朋友生活动态及社会上的热点新闻等,这些都是通过中心化的社交平台来实现。
但是,在中心化的社交平台中,由于供应商能随时掌握你的数据,你的隐私就无法得到保障。而区块链技术能够实现人与人之间交流的去中心化,它不记录和存储任何个人信息,也不向你推送广告,旨在形成点对点的对等社交。
传统社交平台的痛点
在传统社交平台中,你的信息如果被泄露,就可能会给你的生活带来极大的困扰,例如经常收到各种骚扰电话或短信等。而且,在有些社交平台中,你需要提供自己的个人信息才能使用,这些个人信息会被供应商掌握。供应商为了获利,就可能把信息出售给其他企业或不法分子,这就使你的隐私安全很难保障。
控制你的数据
例如,有一位网友表示自己在某电影订票平台上体验到了被“杀熟”的感觉,因为这位网友分别用不同级别的平台会员账号购买同一场次、同一时间段的电影票时,高级别账号的票价反而更贵。
针对这种现象,有专家表示,很多社交平台都会给用户的每一次行为贴上数据标签,有的用户还会产生成千上万个标签,这使社交平台比用户自己还要了解自己。社交平台在获得这些数据后会根据用户标签和习惯来获取利益。
用户的个人信息可能会被多家社交平台共享,从而导致用户不断受到各种骚扰。例如,用户在淘宝中搜索过某件商品,当他浏览某个社交平台时,社交平台的广告栏就会出现类似的商品。在社交平台中,供应商会对用户“画像”,根据所掌握的用户数据来推断用户的喜好,然后有针对性地向用户推荐商品,从而实现对用户的精准营销。
2018 年 1 月 12 日,东南亚及中东最大的社交平台 Mico 发布了全球首个基于区块链技术的社交区块链 GSC,这对于 Facebook、微信等中心化的社交平台来说是一种冲击。区块链技术的去中心化、匿名和数据难以篡改的特性正好契合社交领域的特点,Mico 推出的去中心化社交区块链 GSC 能够有效解决传统社交平台的痛点。
用区块链技术构建一个去中心化的社交平台,能够保障你的数据的安全性,让数据的控制权回到用户手中。社交区块链 GSC 底层利用区块链技术来记录社交平台中的权属信息,用区块链的智能合约解决社交平台中的交易问题。
去中心化的社交区块链 GSC 能够把你的数据使用权归还给你,这样的模式就保证了你个人数据的安全。因此,社交区块链 GSC 有效避免了社交平台的价值垄断,形成了内容生产方、用户、广告方等多方受益的社交生态。
隐私安全难以维护
社交平台的第二个痛点就是你的隐私安全难以维护。生活中经常出现用户隐私被泄露的情况,社交平台成了不法分子盗取用户隐私、进行非法获利的重要渠道。
社交平台的便利性和娱乐性吸引了越来越多的用户加入,成为人们在工作之余的一种休闲方式。从国内的微信、QQ、微博,到国外的 Facebook、 Myspace、SMN 等,都受到了人们的欢迎。很多社交平台都需要用户实名注册、填写个人相关信息后才能使用,这就增加了个人隐私被泄露的概率,因而给用户带来不必要的损失。
社交平台中存储了大量的用户个人数据,但是这些社交平台的隐私保护措施还不够完善,不法分子很容易盗取这些数据。对于社交平台来说,用户填写的个人信息越详细,利用价值就越大。所以,现在很多社交平台都要求用户填写详细的个人信息。这些社交平台会与数据公司合作,把个人隐私当作“商品”贩卖,以此来获得利益。
用户在社交平台注册信息后,很容易造成手机号、社交账号、邮箱账号等被盗,从而产生损失。还有些用户喜欢在社交平台上发布自己的一些动态、分享个人照片、和陌生人聊天互动等,这些与用户相关的信息都可以被数据化,并随时被社交平台收集和记录。
虽然社交平台表示用户的所有隐私信息都会受到保护,但是事实证明,随着数据的增加,用户的隐私安全依然难以维护。
利用区块链的特点改进社交平台
区块链具有去中心化、安全性高、数据难以篡改等特点,将其应用到社交平台中,可以对传统的社交平台进行改进。这种改进表现在多个方面,包括打造分布式社交平台,使个人信息的控制权回到用户手中;实现信息可追溯,提高用户的信任度;通过智能合约扩大用户的自主权;通过加密存储来高度保护用户信息;以去中心化的方式实现点对点的对等社交。
分布式运作:控制权回归用户
传统的社交平台都是中心化运营的,用户对内容、账户和个人信息无控制权。而基于区块链技术的社交平台通过分布式的运作,让内容、账户、个人信息的控制权都回归用户。
目前,有很多创业者利用区块链技术进入社交领域,力图打造新型的分布式社交平台,让控制权回归用户。例如,花椒直播的创始人欧盛创立了基于区块链技术的社交平台 Steemit。用户拥有平台的控制权,可以在自己的社区中进行创作来获得 Token 奖励,还可以通过转售社区来获得收益。花椒直播的区块链社交平台是由无数个内容中心组成的,这就实现了社交平台的分布式运作。
在 Steemit 平台中,用户可以通过发布文章或投票来获得奖励。该平台正在尝试解决内容创作的限制问题,它规定内容创作者的收入通过成员付费来获得,并且使用类似加密货币的系统来激励内容创作者,将收益返还给他们。
可追溯:重塑社交平台信任
传统的社交电商主要以网红电商、内容电商和微信朋友圈电商三大模式为主。这三种模式都是基于用户自身的社交关系网建立信任关系,然后再达成交易。随着社交电商数量的逐渐增多,传统的社交电商也暴露了很多问题,用户之间的信任关系越来越难以构筑。信任都是人为构建的,这种人为构建的信任机制如果出现问题,就容易导致社交电商出现信任危机。
将区块链技术运用于社交电商中,从运营初始阶段就获得用户的信任,通过方便、高效的应用来拉动用户需求,利用社交平台的奖惩机制来维护社交区块链的生态发展。区块链技术的数据难以篡改、可追溯、安全性高的特性有效解决了用户的痛点,提升了用户的信任度。
SEC 推出了以社交信任为基础的区块链系统,它有效地解决了社交电商中的不信任问题。SEC 平台使用户之间容易产生信任基础,也能够保证数据安全,使交易更加高效,并且在主链中有信任背书和监督机制。因此,SEC 实际上是一种基于社交关系权益证明的区块链网络平台。
基于区块链技术的社交电商是一个互动社群,加密的数据化信息代替人成为交易的中心。SEC 将用户信用转变为用户关系信用,将用户或企业征信转变为用户之间交易关系评估。而且,SEC 使用户之间交互关系的性质发生了改变,也增加了社交平台的应用价值。
智能合约:扩大用户的自主权
区块链的智能合约能降低社交平台对用户的控制程度,扩大用户的自主权。
“95 后”创业者徐可为了让用户在社交平台中拥有自主权,基于“区块链 + 社交”创立了 ONO。ONO 是一个去中心化的社交平台,它定义了注意力价值(UNI Quantum,UQ),以此来标记用户的行为,将用户互动的活跃度可视化。用户在平台上的活跃度越高,获得的 UQ 就越多。平台通过兑换的形式回收 UQ,用户通过兑换来获得收益,即使是规模较小的用户也可以获得收益。
在 ONO 平台中,用户产生的所有数据都由自己控制,获得的收益也归自己所有。ONO 平台最核心的业务,就是制作一份由电脑执行的不可更改的智能合约。
在 ONO 平台上,用户的活跃度体现在发表文章及图片、用户之间的互动、参与平台上的游戏等方面。用户的这些行为可以获得 ONO 平台的 UQ(与积分类似)。例如,有一位网名叫“韦物主义”的用户通过 ONO 平台发表了一篇文章,文章获得的点击量和分享次数越多,该用户获得的 UQ 就越多。UQ 是用户自己的数字资产,能够通过平台兑换获得收益。
ONO 是利用区块链技术打造的去中心化社交平台,对所有用户都可用。平台中的数据都归用户自己所有,用户获得的收益都来源于 UQ。ONO 平台不像微信、微博等社交平台那样的中心化管理,也不像腾讯那样由少数几个人来控制、管理用户,该平台由用户自己来控制,从而扩大了用户的自主权。
ONO 平台还打造了各种小游戏(如智力 PK、涂色竞技、聊天匿室等), 以此来吸引更多的年轻用户加入。近几年逐渐兴起的派派、陌陌、微信小程序等都是依靠轻型的社交游戏崛起的,如果 ONO 能够打开这个切入口,将会获得更多的初始用户。
未来,其他社交区块链的开发者会根据 ONO 平台的 SDK 开发去中心化的游戏或小程序,开发者在开发的过程中也会拥有数据处理的权益。
加密存储:高度保护用户数据
在传统的社交平台中,所有数据都存储在社交平台的服务器上。早在 2012 年就有专家估计,Facebook 大约有 18 万台服务器被用来存储用户数据。如果服务器遭到了黑客等不法分子的攻击,很可能会造成用户数据的丢失。
利用区块链技术,社交平台允许用户在自己的设备上通过节点连接到网络中,实现点对点的连接。用户的数据以加密形式存储在区块链的节点中,形成一个分布云。在分布云中,只有知道安全密钥的人才能查看数据。
目前,国内外都出现了一批建立在区块链技术基础上的社交产品。例如,Telegram 是一款手机聊天软件,该软件利用区块链技术对用户的聊天过程进行加密处理,能高度保证用户的隐私安全,用户也能够永久免费使用该软件。
在我国,区块链也成为年轻创业者创业的热点。这些年轻创业者对社交领域和互联网有着广泛而独特的理解,他们开发了各种区块链社交平台。例如,iVeryone 社交平台能够使所有用户参与到社交生态协作体系中,从而获取丰厚的回报。利用区块链技术,iVeryone 将传统社交平台中的收益都还给用户,因而提高了用户参与的积极性。
去中心化:点对点的对等社交
目前,人们所使用的社交平台是完全中心化的,由社交网站来规定用户创造什么样的内容。例如,Facebook、Twitter、微信、微博等都是中心化的社交平台。在中心化的社交平台中,用户数据的安全性无法得到保障。
社交链(SNC)是建立在区块链基础上的去中心化的社交平台,用户在这个平台上可以自由交流。通过点对点的连接,用户数据被存储在区块链的节点中。在区块链中有无数个节点,每个节点都是高度自治的,节点之间也可以自由连接,形成新的单元,它们一起构成了完整的区块链系统。区块链系统具有开放式、扁平化、平等性的特点,这些特点决定了社交链的去中心化。
社交链通过经济激励来增加用户的参与度,提升社交平台的人气。平台最核心的任务就是保护用户原创内容的经济权益。例如,当内容发布者在平台上发布内容时,其他人可以对该内容进行评论或点赞;根据原创内容的评论热度和点赞数,内容发布者就可以获得 SNC 的奖励。除了上述方式,内容发布者还可以出售自己的内容作品。
区块链社交平台未来的演化
区块链技术的发展也让新媒体创业充满希望。以前,社交平台是在交互层面进行创新。如今,基于区块链技术的社交平台将逐渐朝着分层化的方向发展,而且用户在发布内容时就能够获得报酬。
信息分层化
区块链社交平台是一个去中心化的点对点网络平台,其中存在无数个节点,每个节点中都可以存储用户的信息,用户可以根据自己的需求来创建不同身份的社交群组。
例如,根据同事、家人、朋友等不同的身份,用户在生活中会有不同的圈子,这些圈子可以被分为不同的类别。因此,用户在某一个圈子发布信息,就不用担心被不希望看到的人看到,从而实现信息的分层化。
未来,点对点的社交平台会吸引更多的用户加入。例如,对个人隐私非常看重的用户和不喜欢社交平台推送广告的用户等,都会成为区块链社交平台的忠实粉丝。如果用户知道自己目前所用社交平台的安全性低,就会逐渐把兴趣转向区块链社交平台。
在区块链社交平台中,用户可以自己控制所产生的数据。利用区块链信息的分层化来掌控个人信息,用户自身拥有了更多的自治权。
用户发布内容获得报酬
在传统的社交平台中,不管用户发布什么样的内容,也不管用户发布的内容获得了多少评论、分享和点赞,平台基本上是不会给予用户报酬的。用户唯一的收入来源,只能是在个人发布的信息中放置广告,通过广告来获利。但通常情况下,只有拥有大量粉丝的人才会获利。
SELFLLERY 是视觉内容领域的多功能区块链社交平台,用户可以在该平台上分享自己的照片、视频和直播等内容,其整体的业务内容和传统社交平台类似。但是,与传统社交平台不同,用户在 SELFLLERY 平台上可以获得报酬。
用户在 SELFLLERY 平台上发布内容获得的每一个赞或评论、分享,该平台都会给用户的账户计入报酬。SELFLLERY 平台把视觉内容商业化,还为照片库用户提供下载和销售数码照片的机会。
在广告投放方面,SELFLLERY 平台的智能合约系统规避了第三方参与交易的风险,在增加交易参与方数量的同时也使交易变得更加透明。通过智能合约,广告主能够利用 SELFLLERY 平台中知名用户的高知名度来宣传自己的产品。
而且,SELFLLERY 平台在帮助用户获得收益的同时也在帮助别人,它会把每月收入的 10% 捐赠给慈善事业。
以色列 Synereo:挑战中心化社交平台的现状
以色列 Synereo 公司的创始人 Dor Konforty 一直强调: “要建立一个不通过控制用户信息来变现的社交平台。用户之间发消息、发文章等社交活动都可以进行点对点的交互,用户还可以发布收费内容,通过 AMP 来收费。”
Synereo 通过区块链技术建立点对点社交平台的方式,来挑战中心化的社交平台现状。与传统的社交平台(如 Facebook、Twitter 等)不同,Synereo 社交平台无法记录和存储任何用户的信息,也不会向用户推送精准的广告信息。
Synereo 社交平台允许用户在自己的设备上运行节点来连接平台,形成点对点的互联,用户的个人信息通过加密之后被存储在网络的节点中。通过区块链技术对信息加密以后,只有拥有密钥的人才能查看信息。该平台会对做出存储贡献的用户给予一定的补偿,也会对创建和维护内容的用户给予奖励。
通过这种方式,该平台实现了分布式运作,将用户个人信息的控制权归还给用户并向用户提供奖励。这种方式既保证了用户数据的安全,也提高了用户做贡献的积极性。
福利时间到!营长免费送书啦!
本期话题:你认为,未来微信等中心化社交平台会拥抱区块链吗?说出你的理由(50字以上)
营长将从精选留言用户中按留言点赞数抽取排名前5位的幸运者,免费送书一本!
截止时间4月7日(本周日)下午2点!
自2008年中本聪提出区块链的概念至今,区块链技术正陆续被广泛应用到多个领域,形成了“区块链+”模式。 那么,“区块链+”是怎样影响各个领域进而产生价值的呢?
本书在讲述区块链技术特点的基础上,选取金融之外的14个领域进行了详细的阐述 ,包括新零售、医疗、教育、农业、认证、能源、慈善、智慧城市、社交、文娱、物联网、大数据、人工智能及存储。同时,本书选取了当前区块链技术与上述不同领域融合发展的案例,供读者参考,力求能为行业的发展提供可行性的指导建议。
推荐阅读:
猛戳"阅读原文"有惊喜哟!
老铁在看了吗??
深入探讨 React Scheduler 中的核心概念——Lanes(泳道)机制。这是 React 并发模式的基石,用于管理更新的优先级、实现中断和恢复渲染、以及处理 Suspense 等。
免责声明与简化说明:
- 极度复杂: React 的真实 Lanes 实现涉及大量位运算技巧、复杂的优先级计算、与 Suspense 的深度集成以及与 Scheduler 包的交互,源码非常晦涩难懂。
- 核心原理聚焦: 本文将通过 概念性的模拟代码和详尽解释 来阐述 Lanes 的核心思想、数据结构和基本操作流程,旨在让你理解其工作原理,而非提供一份可以直接运行的 React 子集。
- 代码量与清晰度: 我们会编写大量模拟代码和注释来逼近目标行数,但更注重逻辑的清晰性和对核心概念的阐释。
一、 为什么需要 Lanes?解决什么问题?
在 React 的并发模式(Concurrent Mode)之前,更新主要基于 expirationTime
。这种模式难以精细地处理不同来源更新的优先级,也难以实现渲染的可中断与恢复。
Lanes 机制的引入是为了解决以下核心问题:
-
优先级区分: 不同类型的更新应该有不同的优先级。例如:
- 用户输入(如打字)应该具有最高优先级,需要立即响应。
useEffect
或数据获取后的更新优先级较低。startTransition
包裹的更新优先级更低,可以被高优先级任务中断。
-
并发与中断: 低优先级的渲染任务在执行过程中,如果遇到更高优先级的更新(如用户输入),应该能够被中断,优先处理高优先级更新,稍后再恢复或重新开始低优先级渲染。
-
批处理与合并: 多个更新可以属于同一个“批次”或具有兼容的优先级,Lanes 有助于决定哪些更新可以一起处理。
-
Suspense 集成: Lanes 与 Suspense 紧密配合,用于标记挂起的组件、处理
fallback
以及在数据加载后恢复渲染。
二、 Lanes 的核心概念:位掩码 (Bitmask)
Lanes 的核心是使用31位的二进制数来表示不同的优先级。每一位(或几位)代表一个“泳道”(Lane)。
-
为什么是 31 位? JavaScript 中的位运算是基于 32 位有符号整数进行的,最高位是符号位。为了避免符号位带来的复杂性,React 只使用了低 31 位。
-
每个 Lane 是一个位: 每个优先级通常由一个单独的 bit 位表示。例如:
SyncLane
(同步,最高优先级):0b0000000000000000000000000000001
(1)InputContinuousLane
(连续输入):0b0000000000000000000000000000100
(4)DefaultLane
(默认):0b0000000000000000000000000010000
(16)TransitionLane1
(过渡):0b0000000000000000000001000000000
(64)IdleLane
(空闲,最低):0b0100000000000000000000000000000
(很大)- (注意:实际的 Lane 位定义比这复杂得多,包含多个 TransitionLanes、RetryLanes 等,这里是简化示意)
-
Lanes (复数): 通常我们处理的是一个Lanes 集合,用一个 31 位整数表示,其中亮起的位代表包含的 Lane。例如,一个
Lanes
值0b00101
(5) 表示它同时包含了SyncLane
(1) 和InputContinuousLane
(4)。 -
位运算的优势:
-
合并 (Merging): 使用按位或
|
操作可以轻松合并两个 Lanes 集合。lanes1 | lanes2
-
检查包含 (Checking Inclusion): 使用按位与
&
操作可以检查一个 Lanes 集合是否包含某个特定的 Lane,或者两个 Lanes 集合是否有重叠。(lanes & SomeLane) === SomeLane
(是否包含 SomeLane)(lanes & OtherLanes) !== 0
(是否有重叠)
-
移除 (Removing): 使用按位与和按位非
& ~
可以从一个 Lanes 集合中移除另一个 Lanes 集合。lanes & ~lanesToRemove
-
效率高: 位运算是非常快的底层操作。
-
三、 核心数据结构与常量 (模拟)
javascript 代码解读复制代码// --- Lane 常量定义 (高度简化) ---
// 使用 31 位整数,每一位代表一个优先级通道
// 值越小,优先级越高 (因为 LSB 对应的优先级最高)
// 特殊值
const NoLane: Lane = /* */ 0b0000000000000000000000000000000; // 0
const NoLanes: Lanes = /* */ 0b0000000000000000000000000000000; // 0
// 同步 Lane (最高优先级) - 用于 legacy 模式或 ReactDOM.flushSync
const SyncLane: Lane = /* */ 0b0000000000000000000000000000001; // 1
// 输入相关 Lanes (高优先级)
const InputContinuousLane: Lane = /* */ 0b0000000000000000000000000000100; // 4 - 如拖拽
const InputDiscreteLane: Lane = /* */ 0b0000000000000000000000000001000; // 8 - 如点击、输入框输入 (比 Continuous 稍低)
// 默认 Lane (普通优先级) - 大多数更新,如 setState, useEffect
const DefaultLane: Lane = /* */ 0b0000000000000000000000000010000; // 16
// 过渡 Lanes (Transition) - 用于 startTransition 包裹的更新 (较低优先级)
// React 实际有多个 Transition Lanes,这里简化为一个范围
const TransitionLane1: Lane = /* */ 0b0000000000000000000001000000000; // 64
const TransitionLane2: Lane = /* */ 0b0000000000000000000010000000000; // 128
// ... 可能更多
const TransitionLanes: Lanes = /* */ 0b0000000001111111111111000000000; // 假设包含多个 Transition Lane 位
// 重试 Lane (用于 Suspense 失败后重试)
const RetryLane1: Lane = /* */ 0b0000000010000000000000000000000; // ...
const RetryLanes: Lanes = /* */ 0b0001111100000000000000000000000; // 假设包含多个 Retry Lane 位
// 空闲 Lane (最低优先级) - 如 Offscreen API
const IdleLane: Lane = /* */ 0b0100000000000000000000000000000; // 很大
// --- 类型别名 ---
type Lane = number; // 代表单个优先级
type Lanes = number; // 代表一个 Lane 的集合 (位掩码)
// --- 一些常用的 Lanes 集合 ---
const SyncUpdateLanes: Lanes = SyncLane; // 同步更新
const InputUpdateLanes: Lanes = InputContinuousLane | InputDiscreteLane; // 所有输入更新
const DefaultUpdateLanes: Lanes = DefaultLane; // 默认更新
const NonIdleLanes: Lanes = /* */ 0b0011111111111111111111111111111; // 除了 IdleLane 之外的所有 Lanes
// --- Fiber Root 节点上的 Lanes 相关属性 (模拟) ---
interface FiberRootNode {
// ... 其他 root 属性
// 待处理的 Lanes:所有已调度但尚未完成的更新所属 Lanes 的集合
pendingLanes: Lanes;
// 挂起的 Lanes:因为 Suspense 而挂起的更新所属 Lanes 的集合
suspendedLanes: Lanes;
// 被 Ping 的 Lanes:Suspense 的数据加载完成后,用于唤醒挂起任务的 Lanes
pingedLanes: Lanes;
// 已完成的 Lanes:在最近一次提交中完成的 Lanes (用于某些启发式判断)
finishedLanes: Lanes;
// 过期的 Lanes: 已经超过了截止时间,必须同步完成的 Lanes
expiredLanes: Lanes;
// 当前正在渲染的 Lanes 集合 (在 workLoop 中设置)
currentRenderLanes: Lanes;
// 其他与 Lanes 相关的状态...
// eventTimes: LaneMap; // 记录每个 Lane 的调度时间
// expirationTimes: LaneMap; // 记录每个 Lane 的过期时间
}
// --- 更新对象上的 Lane (模拟) ---
interface Update<State> {
// ... 其他更新属性 (payload, callback 等)
lane: Lane; // 这个更新属于哪个 Lane
}
// --- 全局变量 (模拟 React 内部状态) ---
// 当前正在进行的渲染所属的 Lanes 集合
let workInProgressRootRenderLanes: Lanes = NoLanes;
// 当前更新的上下文 Lane (例如,在事件处理函数中可能是 InputDiscreteLane)
let currentUpdateLane: Lane = NoLane;
// 是否在 Transition 更新中
let isTransitionRunning: boolean = false;
// --- Lane 工具函数 (核心操作) ---
/**
* 合并两个 Lanes 集合
* @param a Lanes 集合 A
* @param b Lanes 集合 B
* @returns 合并后的 Lanes 集合
*/
function mergeLanes(a: Lanes, b: Lanes): Lanes {
// 使用按位或 |
return a | b;
}
/**
* 检查 lanes 集合中是否包含 targetLane
* @param lanes 要检查的集合
* @param lane 目标 Lane
* @returns boolean
*/
function includesSyncLane(lanes: Lanes): boolean {
return (lanes & SyncLane) !== NoLane;
}
function includesNonIdleLanes(lanes: Lanes): boolean {
return (lanes & NonIdleLanes) !== NoLane;
}
// 更通用的检查函数
function includesSomeLane(lanes: Lanes, subset: Lanes): boolean {
// 检查两个集合是否有交集 (至少包含 subset 中的一个 lane)
// 使用按位与 &
return (lanes & subset) !== NoLanes;
}
/**
* 检查 subset 是否是 lanes 的子集
* @param lanes 父集
* @param subset 子集
*/
function isSubsetOfLanes(lanes: Lanes, subset: Lanes): boolean {
// 如果 (lanes & subset) 的结果等于 subset 本身,说明 lanes 包含了 subset 的所有位
return (lanes & subset) === subset;
}
/**
* 从 lanes 集合中移除 subset 包含的所有 Lanes
* @param lanes 原始集合
* @param subset 要移除的 Lanes 集合
* @returns 移除后的 Lanes 集合
*/
function removeLanes(lanes: Lanes, subset: Lanes): Lanes {
// 使用按位与和按位非 ~
return lanes & ~subset;
}
/**
* 获取 lanes 集合中优先级最高的 Lane
* (优先级越高,对应的数值越小,即越接近 LSB - Least Significant Bit)
* @param lanes Lanes 集合
* @returns 优先级最高的 Lane,如果没有则返回 NoLane
*/
function getHighestPriorityLane(lanes: Lanes): Lane {
// 利用 LSB 技巧:x & -x 可以得到 x 的最低有效位 (Lowest Set Bit)
// 在我们的 Lane 定义中,最低有效位对应的数值最小,优先级最高
return lanes & -lanes;
}
/**
* 从 lanes 集合中选择一个 Lane 来执行工作
* (真实实现会考虑饥饿、过期等,这里简化为选择最高优先级的)
* @param root Fiber Root
* @param wipLanes 当前正在处理的 Lanes
* @returns 要处理的下一个 Lanes 集合
*/
function getNextLanes(root: FiberRootNode, wipLanes: Lanes): Lanes {
const pendingLanes = root.pendingLanes;
const suspendedLanes = root.suspendedLanes;
const pingedLanes = root.pingedLanes;
// 0. 如果没有待处理的 Lanes,返回 NoLanes
if (pendingLanes === NoLanes) {
return NoLanes;
}
// 1. 检查是否有同步 Lane (最高优先级)
if ((pendingLanes & SyncLane) !== NoLanes) {
console.log("[getNextLanes] 检测到 SyncLane,优先处理");
return SyncLane;
}
// 2. 检查是否有被 Ping 的 Lanes (唤醒 Suspense)
// 需要排除掉当前正在处理的、或者已经挂起的 Lanes
const nonIdlePingedLanes = pingedLanes & NonIdleLanes;
if (nonIdlePingedLanes !== NoLanes) {
const pingedLanesToTry = nonIdlePingedLanes & ~suspendedLanes;
if (pingedLanesToTry !== NoLanes) {
console.log("[getNextLanes] 检测到 Pinged Lanes,尝试处理:", pickArbitraryLane(pingedLanesToTry));
// 真实实现会更复杂,可能涉及优先级比较
return pickArbitraryLane(pingedLanesToTry); // 选择一个被 ping 的 lane
}
}
// 3. 检查是否有输入或其他高优先级 Lanes
const inputAndDefaultLanes = pendingLanes & (InputUpdateLanes | DefaultUpdateLanes);
if (inputAndDefaultLanes !== NoLanes) {
const nextLanes = getHighestPriorityLanes(inputAndDefaultLanes);
console.log("[getNextLanes] 检测到 Input/Default Lanes,选择最高优先级:", nextLanes);
return nextLanes;
}
// 4. 检查是否有 Transition Lanes
const transitionLanes = pendingLanes & TransitionLanes;
if (transitionLanes !== NoLanes) {
const nextLanes = getHighestPriorityLanes(transitionLanes);
console.log("[getNextLanes] 检测到 Transition Lanes,选择最高优先级:", nextLanes);
return nextLanes;
}
// 5. 检查是否有 Retry Lanes
const retryLanes = pendingLanes & RetryLanes;
if (retryLanes !== NoLanes) {
const nextLanes = getHighestPriorityLanes(retryLanes);
console.log("[getNextLanes] 检测到 Retry Lanes,选择最高优先级:", nextLanes);
return nextLanes;
}
// 6. 检查是否有 Idle Lane
if ((pendingLanes & IdleLane) !== NoLanes) {
console.log("[getNextLanes] 检测到 IdleLane,处理");
return IdleLane;
}
// 理论上不应该执行到这里,除非 pendingLanes 为 NoLanes
console.warn("[getNextLanes] 未找到合适的 Lane,返回 NoLanes");
return NoLanes;
}
// 辅助函数:获取一个 Lanes 集合中的所有最高优先级 Lanes (可能不止一个)
function getHighestPriorityLanes(lanes: Lanes): Lanes {
const highestLane = getHighestPriorityLane(lanes);
// 实际 React 中可能包含一个优先级范围内的所有 Lanes,这里简化
return highestLane;
}
// 辅助函数:从 Lanes 集合中随意选择一个 Lane (通常是最高优先级的那个)
function pickArbitraryLane(lanes: Lanes): Lane {
return getHighestPriorityLane(lanes);
}
// 辅助函数:检查 lane 是否在 lanes 集合中
function isLaneIncluded(lanes: Lanes, lane: Lane): boolean {
return (lanes & lane) !== NoLane;
}
console.log("--- Lane 工具函数定义完毕 ---");
四、 Lanes 在更新与调度流程中的应用 (模拟)
javascript 代码解读复制代码// --- 模拟 Fiber Root ---
const root: FiberRootNode = {
pendingLanes: NoLanes,
suspendedLanes: NoLanes,
pingedLanes: NoLanes,
finishedLanes: NoLanes,
expiredLanes: NoLanes,
currentRenderLanes: NoLanes,
// eventTimes: createLaneMap(NoTimestamp),
// expirationTimes: createLaneMap(NoTimestamp),
};
// --- 模拟调度器状态 ---
let isWorkLoopRunning = false; // 是否有 workLoop 在运行
let isCallbackScheduled = false; // 是否已安排回调
/**
* 请求一个适合当前上下文的 Lane
* (真实实现会考虑当前事件优先级等)
* @returns Lane
*/
function requestUpdateLane(): Lane {
// 1. 如果在 Transition 中,分配 Transition Lane
if (isTransitionRunning) {
console.log("[requestUpdateLane] 在 Transition 中,分配 TransitionLane1");
// 实际会从 TransitionLanes 池中选择一个
return TransitionLane1;
}
// 2. 如果当前正在处理输入事件 (React 通过上下文判断)
// 假设我们有一个全局变量模拟这个
// if (currentEventPriority === DiscreteEventPriority) {
// console.log("[requestUpdateLane] 在离散输入事件中,分配 InputDiscreteLane");
// return InputDiscreteLane;
// }
// if (currentEventPriority === ContinuousEventPriority) {
// console.log("[requestUpdateLane] 在连续输入事件中,分配 InputContinuousLane");
// return InputContinuousLane;
// }
// 3. 默认情况,分配 DefaultLane
console.log("[requestUpdateLane] 默认情况,分配 DefaultLane");
return DefaultLane;
}
/**
* 调度一个更新到 Fiber Root
* @param root Fiber Root
* @param lane 更新所属的 Lane
*/
function scheduleUpdateOnFiber(root: FiberRootNode, lane: Lane) {
console.log(`[scheduleUpdate] 收到 Lane ${lane} 的更新请求`);
// 1. 将 Lane 添加到 root 的 pendingLanes
root.pendingLanes = mergeLanes(root.pendingLanes, lane);
console.log(`[scheduleUpdate] root.pendingLanes 更新为: ${root.pendingLanes.toString(2)} (${root.pendingLanes})`);
// 2. 检查是否需要同步执行 (SyncLane 或已过期)
if (lane === SyncLane /* || isLaneExpired(root, lane) */) {
console.log(`[scheduleUpdate] Lane ${lane} 需要同步执行,立即执行 workLoop`);
// 在同步模式下,可能直接触发渲染,或者使用微任务确保在当前任务结束前执行
ensureRootIsScheduled(root, true); // 标记为同步
} else {
// 异步模式,安排调度
console.log(`[scheduleUpdate] Lane ${lane} 是异步的,安排调度`);
ensureRootIsScheduled(root, false);
}
}
/**
* 确保 Root 的工作循环已被安排
* @param root Fiber Root
* @param isSync 是否需要同步执行
*/
function ensureRootIsScheduled(root: FiberRootNode, isSync: boolean) {
if (isWorkLoopRunning) {
// 如果工作循环已经在运行,可能需要标记有新的更高优先级任务插入
console.log("[ensureRootIsScheduled] 工作循环已在运行");
// 真实 React 会在这里处理中断逻辑
return;
}
if (isCallbackScheduled) {
console.log("[ensureRootIsScheduled] 回调已安排,等待执行");
// 可能需要根据新的 lane 优先级调整回调
return;
}
isCallbackScheduled = true;
console.log(`[ensureRootIsScheduled] 安排 ${isSync ? '同步' : '异步'} 回调执行 workLoop`);
if (isSync) {
// 模拟同步执行 (或微任务)
queueMicrotask(() => {
console.log("\n L> [Microtask Sync] 同步回调触发");
isCallbackScheduled = false; // 重置标记
workLoop(root, true); // 执行同步工作循环
});
} else {
// 模拟异步执行 (真实 React Scheduler 使用 MessageChannel 或 setTimeout)
setTimeout(() => {
console.log("\n L> [setTimeout Async] 异步回调触发");
isCallbackScheduled = false; // 重置标记
workLoop(root, false); // 执行异步工作循环
}, 0); // 使用 setTimeout(0) 模拟宏任务调度
}
}
/**
* 主要工作循环 (高度简化)
* @param root Fiber Root
* @param isSync 是否是同步模式
*/
function workLoop(root: FiberRootNode, isSync: boolean) {
if (isWorkLoopRunning) {
console.error("workLoop 重入错误");
return;
}
isWorkLoopRunning = true;
console.log(`\n===== [workLoop ${isSync ? 'Sync' : 'Async'}] 开始 =====`);
console.log(` 当前 root.pendingLanes: ${root.pendingLanes.toString(2)}`);
let performedWork = false;
try {
if (isSync) {
// 同步模式:必须完成所有同步工作
performSyncWorkOnRoot(root);
performedWork = true;
} else {
// 异步模式:可以分片执行,可以被中断
performedWork = performConcurrentWorkOnRoot(root);
}
} finally {
isWorkLoopRunning = false;
console.log(`===== [workLoop ${isSync ? 'Sync' : 'Async'}] 结束 (是否执行了工作: ${performedWork}) =====\n`);
// 检查循环结束后是否还有待处理任务,或者在循环中产生了新任务
if (root.pendingLanes !== NoLanes) {
console.log("[workLoop] 结束后仍有 pendingLanes,重新安排调度");
ensureRootIsScheduled(root, false); // 默认安排异步
}
}
}
/**
* 执行同步渲染工作 (简化)
*/
function performSyncWorkOnRoot(root: FiberRootNode) {
console.log(" [performSyncWork] 开始执行同步工作");
// 在同步模式下,通常只处理 SyncLane
const lanesToRender = SyncLane; // 简化处理
if (!includesSomeLane(root.pendingLanes, lanesToRender)) {
console.log(" [performSyncWork] 没有待处理的同步 Lane,退出");
return;
}
root.currentRenderLanes = lanesToRender;
workInProgressRootRenderLanes = lanesToRender; // 设置全局变量
console.log(` [performSyncWork] 准备渲染 Lanes: ${lanesToRender.toString(2)}`);
// 模拟渲染过程 (遍历 Fiber 树等)
console.log(" [performSyncWork] ...模拟 Fiber 树遍历和组件渲染...");
// 假设渲染成功完成
console.log(" [performSyncWork] 渲染完成");
// 模拟提交阶段
commitRoot(root, lanesToRender);
workInProgressRootRenderLanes = NoLanes; // 清理全局变量
root.currentRenderLanes = NoLanes;
console.log(" [performSyncWork] 同步工作完成");
}
/**
* 执行并发渲染工作 (简化,包含中断检查)
*/
function performConcurrentWorkOnRoot(root: FiberRootNode): boolean {
console.log(" [performConcurrentWork] 开始执行并发工作");
// 1. 选择要渲染的 Lanes (最高优先级)
const lanesToRender = getNextLanes(root, NoLanes); // wipLanes 初始为 NoLanes
if (lanesToRender === NoLanes) {
console.log(" [performConcurrentWork] 没有找到需要渲染的 Lane,退出");
return false; // 没有执行工作
}
// 检查选出的 Lane 是否真的在 pendingLanes 中 (健全性检查)
if (!includesSomeLane(root.pendingLanes, lanesToRender)) {
console.warn(` [performConcurrentWork] getNextLanes 返回了不在 pendingLanes 中的 Lane (${lanesToRender}), 退出`);
return false;
}
root.currentRenderLanes = lanesToRender;
workInProgressRootRenderLanes = lanesToRender; // 设置全局变量
console.log(` [performConcurrentWork] 准备渲染 Lanes: ${lanesToRender.toString(2)} (${lanesToRender})`);
// 模拟渲染过程 (可能是分片的)
let shouldYield = false; // 标记是否需要让出主线程
let workUnitCounter = 0;
const MAX_WORK_UNITS_PER_LOOP = 3; // 模拟时间分片,每次循环最多处理几个单元
while (workUnitCounter < MAX_WORK_UNITS_PER_LOOP) {
workUnitCounter++;
console.log(` [performConcurrentWork] ...模拟处理工作单元 ${workUnitCounter}...`);
// *** 中断检查 ***
// 在处理每个工作单元之间,检查是否有更高优先级的任务插入
const currentPendingLanes = root.pendingLanes;
const higherPriorityLanes = getHighestPriorityLane(currentPendingLanes);
// 如果新来的最高优先级 Lane 比当前正在渲染的 Lane 优先级更高
// (注意:值越小优先级越高)
if (higherPriorityLanes !== NoLane && higherPriorityLanes < getHighestPriorityLane(lanesToRender)) {
console.warn(` [performConcurrentWork] ***** 中断 *****`);
console.warn(` 检测到更高优先级 Lane: ${higherPriorityLanes.toString(2)} (${higherPriorityLanes})`);
console.warn(` 当前渲染 Lanes: ${lanesToRender.toString(2)} (${lanesToRender})`);
// 中断当前渲染,清理状态,让出主线程,等待调度器重新调度
workInProgressRootRenderLanes = NoLanes;
root.currentRenderLanes = NoLanes;
console.log(" [performConcurrentWork] 清理渲染状态,准备让出");
return true; // 执行了部分工作,但被中断
}
// 模拟检查是否需要让出主线程 (基于时间判断)
// if (scheduler.shouldYield()) {
// console.log(" [performConcurrentWork] 时间耗尽,需要让出主线程 (Yield)");
// shouldYield = true;
// break;
// }
}
if (shouldYield) {
// 如果需要让出,当前渲染任务未完成,等待下次调度继续
console.log(" [performConcurrentWork] 本次时间片结束,渲染未完成");
// workInProgressRootRenderLanes 保持不变,等待下次继续
return true; // 执行了部分工作
} else {
// 渲染完成 (当前 Lanes 的工作)
console.log(` [performConcurrentWork] Lanes ${lanesToRender.toString(2)} 的渲染工作完成`);
// 模拟提交阶段
commitRoot(root, lanesToRender);
workInProgressRootRenderLanes = NoLanes; // 清理全局变量
root.currentRenderLanes = NoLanes;
return true; // 执行了完整工作
}
}
/**
* 模拟提交阶段
* @param root Fiber Root
* @param finishedWorkLanes 本次渲染完成的 Lanes
*/
function commitRoot(root: FiberRootNode, finishedWorkLanes: Lanes) {
console.log(` [commitRoot] 开始提交 Lanes: ${finishedWorkLanes.toString(2)}`);
// 1. 从 pendingLanes 中移除已完成的 Lanes
const before = root.pendingLanes;
root.pendingLanes = removeLanes(root.pendingLanes, finishedWorkLanes);
console.log(` [commitRoot] pendingLanes 从 ${before.toString(2)} 更新为 ${root.pendingLanes.toString(2)}`);
// 2. 更新 finishedLanes
root.finishedLanes = finishedWorkLanes; // 记录最近完成的 Lanes
// 3. 模拟执行 DOM 更新、调用 useEffect 回调等
console.log(" [commitRoot] ...模拟 DOM 更新和 Effect 执行...");
console.log(` [commitRoot] 提交完成`);
}
// --- 模拟场景 ---
console.log("\n====== 模拟开始 ======");
console.log("初始 root.pendingLanes:", root.pendingLanes);
// 1. 模拟一个低优先级的 Transition 更新
console.log("\n--- 模拟 Transition 更新 ---");
isTransitionRunning = true; // 进入 Transition 上下文
const transitionLane = requestUpdateLane(); // 获取 TransitionLane
scheduleUpdateOnFiber(root, transitionLane);
isTransitionRunning = false; // 退出 Transition 上下文
// 此时 root.pendingLanes 包含 TransitionLane, workLoop (异步) 被安排
// 2. 几乎同时,模拟一个高优先级的用户输入更新
console.log("\n--- 模拟用户输入更新 (高优先级) ---");
// 假设当前是离散输入事件上下文
// currentEventPriority = DiscreteEventPriority; // (需要更复杂的上下文管理)
// 这里直接使用 InputDiscreteLane
const inputLane = InputDiscreteLane;
scheduleUpdateOnFiber(root, inputLane);
// currentEventPriority = DefaultEventPriority; // 恢复默认
// 此时 root.pendingLanes 包含 TransitionLane 和 InputLane
// workLoop (异步) 可能已被安排,或者会被新的更高优先级更新重新安排/抢占
// 3. 模拟一个同步更新 (最高优先级)
// console.log("\n--- 模拟同步更新 (最高优先级) ---");
// scheduleUpdateOnFiber(root, SyncLane);
// 这会立即 (或在微任务中) 触发 workLoop(Sync)
// 等待异步调度执行... (控制台会显示调度和渲染日志)
// 预期执行流程 (可能因 setTimeout/queueMicrotask 时序略有不同):
// 1. Transition 更新安排异步 workLoop。
// 2. Input 更新到来,pendingLanes 合并 InputLane。由于 Input 优先级更高,
// 如果异步 workLoop 尚未执行,它会被 Input 更新抢占;
// 如果异步 workLoop 正在执行 Transition (不太可能这么快),它会被中断。
// 3. 异步回调触发 workLoop(Async)。
// 4. getNextLanes 选择 InputLane (优先级高于 TransitionLane)。
// 5. performConcurrentWorkOnRoot 开始渲染 InputLane。
// 6. 假设 InputLane 渲染很快完成,调用 commitRoot(InputLane)。
// pendingLanes 移除 InputLane,剩下 TransitionLane。
// 7. workLoop 结束。检查发现 pendingLanes 仍有 TransitionLane,再次安排异步 workLoop。
// 8. 下一个异步回调触发 workLoop(Async)。
// 9. getNextLanes 选择 TransitionLane。
// 10. performConcurrentWorkOnRoot 开始渲染 TransitionLane。
// 11. 假设渲染完成,调用 commitRoot(TransitionLane)。
// 12. pendingLanes 变为空。workLoop 结束。不再安排。
// 如果中间插入了 SyncLane:
// 1. Sync 更新到来,pendingLanes 合并 SyncLane。
// 2. ensureRootIsScheduled 安排同步 workLoop (微任务)。
// 3. 微任务触发 workLoop(Sync)。
// 4. performSyncWorkOnRoot 只处理 SyncLane。
// 5. commitRoot(SyncLane)。pendingLanes 移除 SyncLane。
// 6. workLoop(Sync) 结束。检查发现 pendingLanes 仍有 Input/Transition,安排异步 workLoop。
// 7. 后续流程同上,处理 Input 和 Transition。
五、 总结与关键点
-
位表示优先级: Lanes 使用 31 位整数的位来代表不同的更新优先级,数值越小(越接近 LSB)优先级越高。
-
Lanes 集合: 一个整数可以表示多个 Lanes 的集合,通过位运算进行高效操作(合并、检查、移除)。
-
Fiber Root 状态:
pendingLanes
是核心,记录了所有待处理的更新优先级。suspendedLanes
,pingedLanes
等与 Suspense 相关。 -
调度入口:
scheduleUpdateOnFiber
负责将更新的 Lane 添加到pendingLanes
并触发调度逻辑 (ensureRootIsScheduled
)。 -
调度决策:
ensureRootIsScheduled
根据更新是否同步决定使用微任务还是宏任务来安排workLoop
。 -
工作循环 (
workLoop
):-
选择 Lanes (
getNextLanes
): 根据pendingLanes
和其他状态(Suspense, Ping)选择最高优先级的 Lanes 来执行。 -
执行渲染 (
performSyncWorkOnRoot
/performConcurrentWorkOnRoot
):- 同步模式:一次性完成所有同步工作。
- 并发模式:可以分片执行,并在每个工作单元之间检查是否有更高优先级的更新插入,实现中断。
-
提交 (
commitRoot
): 渲染完成后,将完成的 Lanes 从pendingLanes
中移除,并执行副作用。
-
-
并发与中断: 并发模式下的
performConcurrentWorkOnRoot
通过在渲染过程中检查pendingLanes
中是否有比当前workInProgressRootRenderLanes
更高优先级的 Lane,来实现渲染任务的中断。中断后,调度器会重新安排,优先处理更高优先级的任务。
这个模拟虽然简化了很多细节(如精确的 Lane 分配、过期逻辑、错误处理、复杂的 Suspense 交互、真实的 Scheduler 包集成等),但它展示了 Lanes 机制如何通过位运算管理优先级、如何决定工作内容、以及如何实现并发模式下的中断与恢复的核心思想。理解了 Lanes,就理解了 React 并发更新调度的心脏。
评论记录:
回复评论: