专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

手撕Promise之从0开始实现完整的Promise对象

  1。定义对象分析经典Promise对象
  经典的Promise对象结构代码如下:
  1。查看空Promise对象的结构和输出结果:varpnewPromise(function(resolve,reject){console。log(resolve,reject)})console。log(p)
  输出结果如下:(){〔nativecode〕}(){〔nativecode〕}Promise〔〔Prototype〕〕:Promise〔〔PromiseState〕〕:pending〔〔PromiseResult〕〕:undefined
  2。查看fulfilled状态下的Promise对象:varpnewPromise(function(resolve,reject){resolve(已完成)})console。log(p)
  输出结果如下:Promise{fulfilled:已完成}〔〔Prototype〕〕:Promise〔〔PromiseState〕〕:fulfilled〔〔PromiseResult〕〕:已完成
  3。查看rejected状态下的Promise对象:varpnewPromise(function(resolve,reject){reject(已拒绝)})console。log(p)
  输出结果如下:Promise{rejected:已拒绝}〔〔Prototype〕〕:Promise〔〔PromiseState〕〕:rejected〔〔PromiseResult〕〕:已拒绝Uncaught(inpromise)已拒绝Promise对象的基本结构定义
  根据Promise对象的特点分析,Promise存在状态属性和Promise的值的属性。初始化Promise时需要传入一个回调函数来进行对象的基本设置,回调函数具备两个参数resolve和reject,两个参数均为函数。所以初始化代码如下:functionMyPromise(fn){promise的初始状态为pending,可变成fulfilled或rejected其中之一this。promiseStatependingthis。promiseValueundefinedvarresolvefunction(){}varrejectfunction(){}if(fn){fn(resolve,reject)}else{throw(InitError,PleaseuseafunctiontoinitMyPromise!)}}
  根据对象特性,初始化Promise时的回调函数是同步执行的,所以此时的fn直接调用即可。
  在调用resolve和reject时,需要将Promise对象的状态设置为对应的fulfilled和rejected,其中需要传入Promise当前的结果,所以此时应该将resolve和reject修改为如下结构。保存上下文对象varthisthisvarresolvefunction(value){if(this。promiseStatepending){this。promiseStatefulfilledthis。promiseValuevalue}}varrejectfunction(value){if(this。promiseStatepending){this。promiseStaterejectedthis。promiseValuevalue}}
  定义完内部结构之后需要思考Promise在状态变更为fulfilled以及状态变更为rejected时对应的then和catch会相应执行,所以需要将对象的两个函数初始化:MyPromise。prototype。thenfunction(callback){}MyPromise。prototype。catchfunction(callback){}
  那么初始对象的结构应该整体是这样的:functionMyPromise(fn){promise的初始状态为pending,可变成fulfilled或rejected其中之一this。promiseStatependingthis。promiseValueundefinedvarthisthisvarresolvefunction(value){if(this。promiseStatepending){this。promiseStatefulfilledthis。promiseValuevalue}}varrejectfunction(value){if(this。promiseStatepending){this。promiseStaterejectedthis。promiseValuevalue}}if(fn){fn(resolve,reject)}else{throw(InitError,PleaseuseafunctiontoinitMyPromise!)}}MyPromise。prototype。thenfunction(callback){}MyPromise。prototype。catchfunction(callback){}实现then的调用
  在实现了初始结构之后,我们需要使用MyPromise按照Promise的方式进行编程,来实现他的流程控制部分了。首先我们需要让then跑起来。
  定义调用代码:varpnewMyPromise(function(resolve,reject){resolve(123)})console。log(p)p。then(function(res){console。log(res)})
  此时执行代码时控制台会输出如下内容:MyPromisepromiseState:fulfilledpromiseValue:123〔〔Prototype〕〕:Object
  我们发现我们定义的Promise对象状态已经变更但是then中的回调函数没有执行。
  接下来我们实现then的触发:在MyPromise中改造该部分代码如下定义then的回调函数this。thenCallbackundefinedvarresolvefunction(value){if(this。promiseStatepending){this。promiseStatefulfilledthis。promiseValuevalue异步的执行then函数中注册的回调函数setTimeout(function(){if(this。thenCallback){this。thenCallback(value)}})}}在then中编写如下代码MyPromise。prototype。thenfunction(callback){then第一次执行时注册回调函数到当前的Promise对象this。thenCallbackfunction(value){callback(value)}}
  在两处改造完成之后访问网页会发现控制台上可以输出then函数中的回调执行的结果并且该结果的参数就是resolve传入的值。MyPromise{promiseState:fulfilled,promiseValue:123,thenCallback:undefined}promise。html:51123
  当前代码效果如下:functionMyPromise(fn){promise的初始状态为pending,可变成fulfilled或rejected其中之一this。promiseStatependingthis。promiseValueundefinedvarthisthis定义then的回调函数this。thenCallbackundefinedvarresolvefunction(value){if(this。promiseStatepending){this。promiseStatefulfilledthis。promiseValuevalue异步的执行then函数中注册的回调函数setTimeout(function(){if(this。thenCallback){this。thenCallback(value)}})}}varrejectfunction(value){if(this。promiseStatepending){this。promiseStaterejectedthis。promiseValuevalue}}if(fn){fn(resolve,reject)}else{throw(InitError,PleaseuseafunctiontoinitMyPromise!)}}MyPromise。prototype。thenfunction(callback){then第一次执行时注册回调函数到当前的Promise对象this。thenCallbackfunction(value){callback(value)}}MyPromise。prototype。catchfunction(callback){}varpnewMyPromise(function(resolve,reject){resolve(123)})console。log(p)p。then(function(res){console。log(res)})实现then的异步链式调用
  通过上面的编程已经可以实现then自动触发,但是当前我们如果将代码变成如下效果时只有一个then能执行。而且控制台会报错varpnewMyPromise(function(resolve,reject){resolve(123)})console。log(p)p。then(function(res){console。log(res)})。then(function(res){console。log(res)})。then(function(res){console。log(res)})
  控制台信息如下:MyPromise{promiseState:fulfilled,promiseValue:123,thenCallback:undefined}promise。html:52UncaughtTypeError:Cannotreadpropertiesofundefined(readingthen)atpromise。html:52(anonymous)promise。html:52promise。html:51123
  针对该情况,我们需要对Promise的流程控制代码做进一步的加强以实现链式调用,并且在链式调用的过程中将每次的结果顺利的向下传递。resolve部分代码实现varresolvefunction(value){if(this。promiseStatepending){this。promiseValuevaluethis。promiseStatefulfilled当传入的类型是Promise对象时if(valueinstanceofMyPromise){value。then(function(res){this。thenCallback(res)})}else{当传入的数据类型是普通变量时setTimeout(function(){if(this。thenCallback){this。thenCallback(value)}})}}}then函数代码实现MyPromise。prototype。thenfunction(callback){varthisthisreturnnewMyPromise(function(resolve,reject){this。thenCallbackfunction(value){varcallbackRescallback(value)resolve(callbackRes)}})}
  将then代码修改为如下之后我们将调用代码更改如下varpnewMyPromise(function(resolve){resolve(newMyPromise(function(resolve1){resolve1(aaa)}))})p。then(function(res){console。log(res)return123})。then(function(res){console。log(res)returnnewMyPromise(function(resolve){setTimeout(function(){resolve(Promise)},2000)})})。then(function(res){console。log(res)})console。log(p)
  会惊喜的发现MyPromise对象可以正常的工作了并且还可以实现何时调用resolve何时执行then的操作MyPromise{promiseValue:MyPromise,promiseState:fulfilled,catchCallback:undefined,thenCallback:}test。html:57aaatest。html:60123test。html:67Promise
  当前状态的代码如下functionMyPromise(fn){varthisthisthis。promiseValueundefinedthis。promiseStatependingthis。thenCallbackundefinedthis。catchCallbackundefinedvarresolvefunction(value){if(this。promiseStatepending){this。promiseValuevaluethis。promiseStatefulfilledif(valueinstanceofMyPromise){value。then(function(res){this。thenCallback(res)})}else{setTimeout(function(){if(this。thenCallback){this。thenCallback(value)}})}}}varrejectfunction(err){}if(fn){fn(resolve,reject)}else{throw(InitError,PleaseuseafunctiontoinitMyPromise!)}}MyPromise。prototype。thenfunction(callback){varthisthisreturnnewMyPromise(function(resolve,reject){this。thenCallbackfunction(value){varcallbackRescallback(value)resolve(callbackRes)}})}varpnewMyPromise(function(resolve){resolve(newMyPromise(function(resolve1){resolve1(aaa)}))})实现catch的流程处理
  当Promise的对象触发reject操作的时候他的状态会变更为rejected,此时会触发catch函数,并且catch函数触发后流程结束。
  首先仿照then的方式在MyPromise对象中定义好初始通知函数定义catch的回调函数this。catchCallbackundefinedvarrejectfunction(err){if(this。promiseStatepending){this。promiseValueerrthis。promiseStaterejectedsetTimeout(function(){if(this。catchCallback){this。catchCallback(err)}})}}
  然后在catch函数中做如下处理MyPromise。prototype。catchfunction(callback){varthisthisreturnnewMyPromise(function(resolve,reject){this。catchCallbackfunction(errValue){varcallbackRescallback(errValue)resolve(callbackRes)}})}
  调用代码如下varpnewMyPromise(function(resolve,reject){reject(err)})p。catch(function(err){console。log(err)})
  当运行此时代码时我们会发现我们的Promise对象在控制台上可以直接触发catch的回调执行并输出对应的结果MyPromise{promiseValue:err,promiseState:rejected,thenCallback:undefined,catchCallback:}test。html:73err实现跨对象执行catch
  在上面的案例中已经可以执行MyPromise的catch函数了,但是如果将调用代码改为如下行为会发现catch函数不会执行varpnewMyPromise(function(resolve,reject){reject(123)})console。log(p)p。then(function(res){console。log(res)})。catch(function(err){console。log(err)})
  这是因为按照我们编写的代码流程Promise对象会自动变更状态为rejected并且catch的回调函数无法注册,所以Promise的流程就断了。这个时候需要追加判断代码让Promise在rejected时如果没有catchCallback再去检测是否存在thenCallbackvarrejectfunction(err){if(this。promiseStatepending){this。promiseValueerrthis。promiseStaterejectedsetTimeout(function(){if(this。catchCallback){this。catchCallback(err)}elseif(this。thenCallback){this。thenCallback(err)}else{throw(thisPromisewasreject,butcannotfoundcatch!)}})}}
  该步骤操作完毕之后我们需要将then函数中的逻辑再次更改为如下MyPromise。prototype。thenfunction(callback){varthisthis实现链式调用并且每个节点的状态是未知的所以每次都需要返回一个新的Proimse对象returnnewMyPromise(function(resolve,reject){then第一次执行时注册回调函数到当前的Promise对象this。thenCallbackfunction(value){判断如果进入该回调时Promise的状态为rejected那么就直接触发后续Promise的catchCallback直到找到catchif(this。promiseStaterejected){reject(value)}else{varcallbackRescallback(value)resolve(callbackRes)}}})}
  修改如下之后调用代码改造为varpnewMyPromise(function(resolve,reject){reject(err)})p。then(function(res){console。log(res)return111})。then(function(res){console。log(res)return111})。then(function(res){console。log(res)return111})。catch(function(err){console。log(err)})console。log(p)
  输出结果为MyPromise{promiseValue:err,promiseState:rejected,catchCallback:undefined,thenCallback:}test。html:91err实现链式调用的中断
  本文仅介绍通过返回Promise对象来中断链式调用,首先在Promise的原型对象上增加reject方法如下:MyPromise。rejectfunction(value){returnnewMyPromise(function(resolve,reject){reject(value)})}
  然后初始化如下调用代码varpnewMyPromise(function(resolve,reject){resolve(123)})console。log(p)p。then(function(res){console。log(then1执行)return456})。then(function(res){console。log(then2执行)returnMyPromise。reject(中断了)})。then(function(res){console。log(then3执行)return789})。then(function(res){console。log(then4执行)return666})。catch(function(err){console。log(catch执行)console。log(err)})
  最后修改调试代码中的thenMyPromise。prototype。thenfunction(callback){varthisthisreturnnewMyPromise(function(resolve,reject){this。thenCallbackfunction(value){if(this。promiseStaterejected){reject(value)}else{varcallbackRescallback(value)if(callbackResinstanceofMyPromise){if(callbackRes。promiseStaterejected){callbackRes。catch(function(errValue){reject(errValue)})}}else{resolve(callbackRes)}}}})}
  根据代码分析处理逻辑,然后查看运行结果:MyPromise{promiseState:fulfilled,promiseValue:123,thenCallback:undefined,catchCallback:undefined}promise。html:100then1执行promise。html:103then2执行promise。html:112catch执行promise。html:113中断了
  最后我们发现在返回Promise。reject()之后then的链式调用便中断了。实现all和race
  1。Promise。all的实现MyPromise。allfunction(promiseArr){varresArr〔〕varerrValueundefinedvarisRejectedfalsereturnnewMyPromise(function(resolve,reject){for(vari0;ipromiseArr。length;i){(function(i){promiseArr〔i〕。then(function(res){resArr〔i〕resletrpromiseArr。every(item{returnitem。promiseStatefulfilled})if(r){resolve(resArr)}})。catch(function(err){isRejectedtrueerrValueerrreject(err)})})(i)if(isRejected){break}}})}
  1。Promise。race的实现MyPromise。racefunction(promiseArr){varendfalsereturnnewMyPromise(function(resolve,reject){for(vari0;ipromiseArr。length;i){(function(i){promiseArr〔i〕。then(function(res){if(endfalse){endtrueresolve(res)}})。catch(function(err){if(endfalse){endtruereject(err)}})})(i)}})}实现generator的调用
  执行器代码如下:fn:Generator函数对象functiongeneratorFunctionRunner(fn){定义分步对象letgeneratorfn()执行到第一个yieldletstepgenerator。next()定义递归函数functionloop(stepArg,generator){获取本次的yield右侧的结果letvaluestepArg。value判断结果是不是Promise对象if(valueinstanceofMyPromisevalueinstanceofPromise){如果是Promise对象就在then函数的回调中获取本次程序结果并且等待回调执行的时候进入下一次递归value。then(function(promiseValue){if(stepArg。donefalse){loop(generator。next(promiseValue),generator)}})}else{判断程序没有执行完就将本次的结果传入下一步进入下一次递归if(stepArg。donefalse){loop(generator。next(stepArg。value),generator)}}}执行动态调用loop(step,generator)}
  调用代码如下:functiontest(){letres1yieldnewMyPromise(function(resolve){setTimeout(function(){resolve(第一秒)},1000)})console。log(res1)letres2yieldnewMyPromise(function(resolve){setTimeout(function(){resolve(第二秒)},1000)})console。log(res2)letres3yieldnewMyPromise(function(resolve){setTimeout(function(){resolve(第三秒)},1000)})console。log(res3)}generatorFunctionRunner(test)总结
  通过简单的代码片段我们便可以快速的实现一个微型的Promise对象,实现手写代码封装Promise对象虽然对工作没有太大的帮助,但是如果可以根据分析Promise的特性,通过JS原始的异步流程控制方式,来仿真成功Promise对象的内部逻辑,就代表你的JS编程水平已经脱离了普通业务开发的程序员的水平了,希望本文的思路可以给您提供帮助,最后附上源代码。源代码functionMyPromise(fn){varthisthisthis。promiseValueundefinedthis。promiseStatependingthis。thenCallbackundefinedthis。catchCallbackundefinedvarresolvefunction(value){if(this。promiseStatepending){this。promiseValuevaluethis。promiseStatefulfilledif(valueinstanceofMyPromise){if(this。thenCallback){value。then(function(res){this。thenCallback(res)})}}else{setTimeout(function(){if(this。thenCallback){this。thenCallback(value)}})}}}varrejectfunction(err){if(this。promiseStatepending){this。promiseValueerrthis。promiseStaterejectedsetTimeout(function(){if(this。catchCallback){this。catchCallback(err)}elseif(this。thenCallback){this。thenCallback(err)}else{throw(thisPromisewasreject,butcannotfoundcatch!)}})}}if(fn){fn(resolve,reject)}else{throw(InitError,PleaseuseafunctiontoinitMyPromise!)}}MyPromise。prototype。thenfunction(callback){varthisthisreturnnewMyPromise(function(resolve,reject){this。thenCallbackfunction(value){if(this。promiseStaterejected){reject(value)}else{varcallbackRescallback(value)if(callbackResinstanceofMyPromise){if(callbackRes。promiseStaterejected){callbackRes。catch(function(errValue){reject(errValue)})}}else{resolve(callbackRes)}}}})}MyPromise。prototype。catchfunction(callback){varthisthisreturnnewMyPromise(function(resolve,reject){this。catchCallbackfunction(errValue){varcallbackRescallback(errValue)resolve(callbackRes)}})}MyPromise。rejectfunction(value){returnnewMyPromise(function(resolve,reject){reject(value)})}MyPromise。resolvefunction(value){returnnewMyPromise(function(resolve){resolve(value)})}MyPromise。allfunction(promiseArr){varresArr〔〕varerrValueundefinedvarisRejectedfalsereturnnewMyPromise(function(resolve,reject){for(vari0;ipromiseArr。length;i){(function(i){promiseArr〔i〕。then(function(res){resArr〔i〕resletrpromiseArr。every(item{returnitem。promiseStatefulfilled})if(r){resolve(resArr)}})。catch(function(err){isRejectedtrueerrValueerrreject(err)})})(i)if(isRejected){break}}})}MyPromise。racefunction(promiseArr){varendfalsereturnnewMyPromise(function(resolve,reject){for(vari0;ipromiseArr。length;i){(function(i){promiseArr〔i〕。then(function(res){if(endfalse){endtrueresolve(res)}})。catch(function(err){if(endfalse){endtruereject(err)}})})(i)}})}

哪里是世界第一个迎来新年第一缕阳光的地方?为什么是基里巴斯?新的一年就要来了,如果你想最先看到新年第一缕阳光,那就去基里巴斯吧。大洋洲的太平洋小岛国基里巴斯比地球上的任何人都更早庆祝新年前夜,它是第一个看到新年第一缕阳光的地方。基里巴斯共和是谁让女团NewJeans的Y2K美学影响世界?NewJeans近期成为现象级女团,被GQBillboard等评价为下一个席卷世界的韩国女团,5位成员在MV日常中的穿搭,也备受Y2KBlokecore等风格玩家关注,而MeeHe生产环境定位日志太麻烦怎么办?建议了解一下日志框架的MDC功能对于每一个开发者来说,查询接口的执行日志都是一个高频率的操作,每当测试说接口有问题时,我们都需要去服务器或者日志系统上查报错的原因。一般情况下,我们会通过对应的关键字或者接口地址去Carbohydr。Polym。为植入物披上凝胶外衣赋予多功能抗菌活性对于传统的单功能抗菌涂层治疗将其用于植入相关的感染并不能实现长期效果。因此,生物医学植入致力于开发新型抗菌涂层,通过结合多种抗菌策略实现相互协同作用以增强抗菌效果。其中,Ti6Al第7篇基础(七)实现Qt文本查找功能导语这一篇我们来加上查找菜单的功能。因为要涉及QtCreator的很多实用功能,所以单独用一篇文章来介绍。以前都用设计器设计界面,而这次我们用代码实现一个简单的查找对话框。除了讲解绘制一张透明背景的单色位图在上一篇文章中,我留下了一个谜题如何使用透明背景绘制一张单色位图。今天我们来揭晓谜底。丑话说前头,我不是一名GDI方面的专家,所以,除了下面讲述的两种方法之外,可能还有我所不知道的汉兰达对手来了!轴距加长100mm,福特新一代锐界于2023年上市!现款第二代锐界于2015年上市,当时的它是少有可以在丰田汉兰达手中抢过订单的车型。但由于市场格局多变,以及自身产品未能迭代更新跟上时代脚步,现款的锐界已经淡出了我们视野。长安福特锐陈国军一生中最爱最恨的都是前妻刘晓庆,大儿子陈赫是他的骄傲2015年,陈国军和刘晓庆在离婚数年后首次同台,台上的两人谈笑风生,刘晓庆还把手亲密的搭在陈国庆的肩膀上。台上的陈国军直言刘晓庆是我人生中最重要的女人,说罢这句话,两人默契的给了对当代散文石榴石戒指文王春华没想到在2022年的最后一天,我拥有了一个石榴石戒指。这是老伴对我的承诺,他说他拿到退休工资的第一个月,一定要给我买件首饰。如今他兑现了。被新冠折磨,过了炼狱般的十天,等人赏读一场灵魂的相遇作者夜伴晨听倘若真正遇到在乎的人那一定是一场灵魂的相遇只有契合的灵魂才可以相伴长久我们相遇在漆黑的夜里天上那轮满月格外的亮清冷的月光洒在街道上路上的几人显得格外寂寥我独坐窗前与月亮你好我的城用生命守护生命视频加载中交大一附院心血管外科主任闫炀来到我们医院,来到我们科室,都是些非常急危重症的病人,家属也很担心,但是我们经常给家属这样说,虽然病情非常重,但是有我们在,您放心。交大一附院
katespade趣致呈献2023中国兔年限定系列兔CUTE之作玩转新春喜悦氛围新春邀约,如期而至。为迎接2023癸卯兔年,纽约时尚及生活方式品牌katespade从生肖兔中汲取创意设计灵感,并打造品牌专属灵兔图腾与花纹,融合一众经典款式,趣致呈献中国新年限定国社小哥年度盘点朋友可以有夺笋?!来源新华社放眼国际朋友圈,一些所谓的朋友实为损友全天候监视盟国,却贼喊捉贼要盟国当小跟班,否则就给脸色看施压切断盟国能源命脉,自己却从中大发横财辞旧迎新之际,国社小哥郑锦强串联起一三十三朵玫瑰去年10月1日,是我和妻子结婚33周年纪念日,我精心给她准备了一个特别的惊喜。前一天晚上,我悄悄对两个孩子说,不要跟妈妈提结婚纪念日的事,就算妈妈说出来,你们也不要有什么表现。妈妈单床位扫描仅20秒!我国成功开发第二代ampampquot数字PETampampquot记者近日从国家药品监督管理局获悉,由华中科技大学数字PET团队开发型号为DigitMI930的新一代全数字PETCT日前通过中国医疗器械注册认证,正式获准进入市场。相关指标显示,D冬天湿热易伤人,用这两物泡水喝,清热利湿,好处多多!冬季进补来年打虎可今天冬补路上竟然出现了一只拦路虎这只老虎就是体内的湿邪北方人久居暖气充足的室内当室内的干燥遇上湿邪就表现为湿热毛老师带来一杯清利湿热的代茶饮,芳香清淡冯大厨以它为健康养生知识!前列腺是男人的生命腺,男人什么时候都得对它好点欢迎来看新一期的健康养生聊一聊!我是华二少。今天我们要来说说前列腺,这前列腺对于很多男同胞来说呢,是很重要很重要的。但是呢有人了解有人不太了解,前列腺它不但影响着排尿这事,还影响着动动脚趾让肠胃更健康中医经络理论提出,人体的五脏六腑在脚上都有相应的投影,连接人体脏腑的12条经脉,其中有6条起于足部。脚是足三阴之始,足三阳之终,双脚分布有60多个穴位与内外环境相通。现代医学认为,禁止!阳康后吃这些东西,或致疾病复发!此类人员特别注意新冠感染初愈后,身体仍需要大量营养来保证免疫系统的能量供给,但要注意食补不能操之过急,一定要给身体留下充足的休养时间。阳康后这些东西不要立即吃食补大吃大喝或致疾病复发据杭州市中医院除了多吃少动,还有3个小习惯让你长胖!太意外了柯大夫,你好!作为上班族的我,平时很少吃那些肥腻的食物,偶尔还会去做运动,尽管这样,我还是越来越胖了,这是为什么呢?家医柯大夫其实,一个人体重上升的原因有很多,其中很多还真让人意想躁渴难耐,渴饮千杯不解,一味石膏助你清热解渴你以为的石膏是用来骨折后固定的,其实石膏的药用价值也非常大!口渴,生活中有一类人,他们很爱喝水,因为渴呀,有时候放个水杯在旁边一直喝还是口渴,我们叫渴饮千杯不解。还有的人一顿饭吃三咳嗽痰多,但是痰咳不出来?来看看吃什么咳嗽化痰吧!新冠感染后,病毒入侵呼吸道刺激呼吸道粘膜,引发咳嗽。此时病原体刺激身体的免疫功能,使患者出现发热,病毒破坏的呼吸道黏膜细胞不会在此时就马上脱落。随着疾病进展,细胞会开始出现脱落的情
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网