当前位置: 首页 > news >正文

理性仁网站如何做估值分析营业推广经典案例

理性仁网站如何做估值分析,营业推广经典案例,elementor做视频网站,唐山哪家做网站好promise的概念已经出现很久了#xff0c;浏览器、nodejs都已经全部实现promise了。现在来聊#xff0c;是不是有点过时了#xff1f; 确实#xff0c;如果不扯淡#xff0c;这篇随笔根本不会有太多内容。所以#xff0c;我就尽可能的#xff0c;多扯一扯#xff0c;聊一…  promise的概念已经出现很久了浏览器、nodejs都已经全部实现promise了。现在来聊是不是有点过时了   确实如果不扯淡这篇随笔根本不会有太多内容。所以我就尽可能的多扯一扯聊一聊promise的另一面。   大家应该都知道怎么创建一个promise var promise new Promise(resolve {setTimeout(() resolve(tarol), 3000) });如果从业时间长一点会知道以前的promise不是这么创建的。比如如果你用过jqueryjquery在1.5引入deferred的概念里面是这样创建promise的 var defer $.Deferred(); var promise defer.promise();如果你用过angular里面有个promise service叫$q它又是这么创建promise的 var defer $q.defer(); var promise defer.promise;好了这里已经有三种创建promise的方式了。其中第一种是现在最常见的第二种和第三种看上去很像但却有细微的差别。比如jquery里面是通过执行函数promise()返回promise而angular中defer的属性就是promise。如果你还有兴趣那么我从头开始讲。   promise的引入是为了规范化异步操作随着前端的逻辑越来越复杂异步操作的问题越来越亟待解决。首先大量的异步操作形成了N级的大括号俗称“回调地狱”其次callback的写法没有标准nodejs里面的callback一般是(err, data) {...}jquery里面的success callback又是data {...}。在这种场景下很多异步流程控制的类库应运而生。   作为前端一般最早接触promise的概念是在jquery的1.5版本发布的deferred objects。但是前端最早引入promise的概念的却不是jquery而是dojo而且promise之所以叫promise也是因为dojo。Promises/A标准的撰写者KrisZyp于09年在google的CommonJS讨论组发了一个贴子讨论了promise API的设计思路。他声称想将这类API命名为future但是dojo已经实现的deferred机制中用到了promise这个术语所以还是继续使用promise为此机制命名。之后便有了CommonJS社区的这个proposal即Promises/A。如果你对什么是deferred什么是promise还存在疑问不要急先跳过后面会讲到。   Promises/A是一个非常简单的proposal它只阐述了promise的基本运行规则 promise对象存在三种状态unfulfilled, fulfilled和failed一旦promise由unfulfilled切换为fulfilled或者failed状态它的状态不可再改变proposal没有定义如何创建promisepromise对象必须包含then方法then(fulfilledHandler, errorHandler, progressHandler)交互式promise对象作为promise对象的扩展需要包含get方法和call方法get(propertyName)、call(functionName, arg1, arg2, ...)  如果你研究过现在浏览器或nodejs的promise你会发现Promises/A好像处处相似但又处处不同。比如三种状态是这个叫法吗progressHandler没见过啊get、call又是什么鬼前面两个问题可以先放一放因为后面会做出解答。第三个问题这里解释下什么是get什么是call它们的设计初衷是什么应用场景是什么虽然现在你轻易见不到它们了但是了解它们有助于理解后面的部分内容。   一般来说promise调用链存在两条管道一条是promise链就是下图一中的多个promise一条是回调函数中的值链就是下图二中的多个value或reason      现在我们都知道值链中前一个callbackcallback1的返回值是后一个callbackcallback2的入参这里仅讨论简单值类型的fulfilled的情况。但是如果我callback1返回的是a而callback2的入参我希望是a.b呢或许你可以说那我callback1返回a.b就是了那如果callback1和callback2都是固定的业务算法它们的入参和返回都是固定的不能随便修改那又怎么办呢如果promise只支持then那么我们需要在两个then之间插入一个新的thenpromise.then(callback1).then(a a.b).then(callback2)。而get解决的就是这个问题有了get后可以这么写promise.then(callback1).get(b).then(callback2)这样promise链条中就可以减少一些奇怪的东西。同理当a.b是一个函数而callback2期望的入参是a.b(c)那么可以这样写promise.then(callback1).call(b, c).then(callback2)。   我们回到之前的话题现在常见的promise和Promise/A到底是什么关系为什么会有花非花雾非雾的感觉原因很简单常见的promise是参照Promises/A的进阶版——Promises/A定义的。   Promises/A存在一些很明显的问题如果你了解TC39 process或者RFC等标准审核流程你会发现 首先Promise/A里面用语不规范尤其是对术语的使用只描述API的用途没有详细的算法  Promises/A就是基于这样的问题产生的要说明的是Promises/A的维护者不再是前面提到的KrisZyp而是由一个组织维护的。   组织的成员如下其中圈出来的另一个Kris需要留意一下之后还会提到他。   Promises/A在Promises/A的基础上做了如下几点修正 移除了then的第三个入参progressHandler所以你见不到了移除了交互式promise的APIget和call所以你用不了了规定promise2 promise1.then(...)中允许promise1 promise2但是文档必须对此情况进行说明promise的三种状态术语化pendingfulfilledrejected规定fulfilled传递的参数叫valuerejected传递的参数叫reason严格区分thenable和promisethenable作为promise的鸭子类型存在thenable是什么、鸭子类型是什么下面会解释使用正式且标准的语言描述了then方法的逻辑算法promises-aplus还提供了验证实现的test case  Promises/A没有新增任何API而且删掉了Promises/A的部分冗余设计。这样一来Promises/A其实只规定了promise对象必须包含指定算法的方法then。接下来我会归整下所谓的then算法以及它存在哪些不常见的调用方式。 then的基本调用方式promise.then(onFulfilled, onRejected)我默认你已经掌握了基础的then调用所以常见的场景以下不做举例。 onFulfilled和onRejected都是可选的如果省略了或者类型不是函数前面流过来的value或者reason直接流到下一个callback我们举两个极端的例子 Promise.resolve(resolve).then().then(value console.log(value)) // resolve Promise.reject(reject).then().then(void 0, reason console.log(reason)) //reason这个特性决定了我们现在可以这样写异常处理 Promise.reject(reason).then(v v).then(v v).then(v v).catch(reason console.log(reason)) //reason但是如果你在then链条中插入一个空的onRejectedreason就流不到catch了。因为onRejected返回了undefined下一个promise处于fulfilled态 Promise.reject(reason).then(v v).then(v v).then(v v, () {}).catch(reason console.log(reason))onFulfilled或onRejected只能调用一次且只能以函数的形式被调用对应的是不能以属性方法的方式被调用比如 var name tarol; var person {name: okal,say: function() {console.log(this.name);} } person.say(); //okal Promise.resolve(value).then(person.say); //tarol如果你想第二行还是打印出okal请使用bind Promise.resolve(value).then(person.say.bind(person)); //okalvar promise2 promise1.then(onFulfilled, onRejected)onFulfilled或者onRejected中抛出异常则promise2状态置为rejected 上面的例子中onFulfilled或者onRejected如果返回了任意值x如果不存在return语句则是返回undefined则进入解析过程[[Resolve]](promise2, x) 解析过程[[Resolve]](promise2, x)算法如下如果x是promise则promise2的状态取决于x的状态那么你会想如果x promise2呢promise2的状态取决于本身的状态这就像把obj的原型设置为自身一样肯定是不允许的。所以其实在第一条规则之前还有一条如果x promise2抛出TypeError。之所以把这条规则放到下面是用前一条规则引出这条规则的必要性如果x不是对象promise2置为fulfilledvalue为x如果x是对象访问x.then时如果抛出异常则promise2置为rejectedreason为抛出的异常 var obj {get then() {throw err}}; Promise.resolve(value).then(v obj).catch(reason console.log(reason)); // err如果then不是函数则同3 Promise.resolve(value).then(v {return {name: tarol,then: void 0} }).then(v console.log(v.name)); //tarol如果then是函数那么x就是一个thenablethen会被立即调用传入参数resolve和reject并绑定x作为this。如果执行过程中调用了resolve(y)那么进入下一个解析过程[[Resolve]](promise2, y)可以看出解析过程实际上是一个递归函数如果调用了reject(r)那么promise2置为rejectedreason为r调用resolve或reject后后面的代码依然会运行 Promise.resolve(value).then(v {return {then: (resolve, reject) {resolve(v);console.log(continue); // continue}} }).then(v console.log(v)); // value如果既调用了resolve、又调用了reject仅第一个调用有效 Promise.resolve(value).then(v {return {then: (resolve, reject) {resolve(resolve);reject(reject)}} }).then(v console.log(v), r console.log(r)); // resolve如果抛出了异常而抛出的时机在resolve或reject前promise2置为rejectedreason为异常本身。如果抛出的时机在resolve或reject之后则忽略这个异常。以下case在chrome 66上运行失败promise处于pending状态不切换但是在nodejs v8.11.1上运行成功 Promise.resolve(value).then(v {return {then: (resolve, reject) {resolve(resolve);throw err;}} }).then(v console.log(v), r console.log(r)); // resolvePromise.resolve(value).then(v {return {then: (resolve, reject) {throw err;resolve(resolve);}} }).then(v console.log(v), r console.log(r)); // err   上面的例子中涉及到一个重要的概念就是thenable。简单的说thenable是promise的鸭子类型。什么是鸭子类型搜索引擎可以告诉你更详尽的解释长话短说就是“行为像鸭子那么它就是鸭子”即类型的判断取决于对象的行为对象暴露的方法。放到promise中就是一个对象如果存在then方法那么它就是thenable对象可以作为特殊类型promise和thenable进入promise的值链。   promise和thenble如此相像但是为什么在解析过程[[Resolve]](promise2, x)中交由不同的分支处理那是因为虽然promise和thenable开放的接口一样但过程角色不一样。promise中then的实现是由Promises/A规定的见then算法入参onFulfilled和onRejected是由开发者实现的。而thenable中then是由开发者实现的入参resolve和reject的实现是由Promises/A规定的见then算法3.3.3。thenable的提出其实是为了可扩展性其他的类库只要实现了符合Promises/A规定的thenable都可以无缝衔接到Promises/A的实现库中。   Promises/A先介绍到这里了。如果你细心你会发现前面漏掉了一个关键的内容就是之前反复提到的如何创建promise。Promise/A中并没有提及而在当下来说new Promise(resolver)的创建方式仿佛再正常不过了普及程度让人忘了还有deferred.promise这种方式。那么Promise构造器又是谁提出来的它为什么击败了deferred成为了promise的主流创建方式   首先提出Promise构造器的标准大名鼎鼎就是es6。现在你见到的promise一般都是es6的实现。es6不仅规定了Promise构造函数还规定了Promise.all、Promise.race、Promise.reject、Promise.resolve、Promise.prototype.catch、Promise.prototype.then一系列耳熟能详的APIPromise.try、Promise.prototype.finally尚未正式成为es标准其中then的算法就是将Promises/A的算法使用es的标准写法规范了下来即将Promises/A的逻辑算法转化为了es中基于解释器API的具体算法。   那么为什么es6放弃了大行其道的deferred最终敲定了Promise构造器的创建方式呢我们写两个demo感受下不同 var Q require(q);var deferred Q.defer();deferred.promise.then(v console.log(v));setTimeout(() deferred.resolve(tarol), 3000);var p new Promise(resolve {setTimeout(() resolve(tarol), 3000); });p.then(v console.log(v));前者是deferred方式需要依赖类库Q后者是es6方式可以在nodejs环境直接运行。   如果你习惯使用deferred你会觉得es6的方式非常不合理   首先promise的产生的原因之一是为了解决回调地狱的问题而Promise构造器的方式在构造函数中直接注入了一个函数如果这个函数在复杂点同样存在一堆大括号。   其次promise基于订阅发布模式实现deferred.resolve/reject可以理解为发布器/触发器triggerdeferred.promise.then可以理解为订阅器on。在多模块编程时我可以在一个公共模块创建deferred然后在A模块引用公共模块的触发器触发状态的切换在B模块引用公共模块使用订阅器添加监听者这样很方便的实现了两个没有联系的模块间互相通信。而es6的方式触发器在promise构造时就生成了并且立即进入触发阶段即创建promise到promise被fulfill或者reject之间的过程自由度减少了很多。   我一度很反感这种创建方式认为这是一种束缚直到我看到了bluebirdPromise/A的实现库讨论组中某个帖子的解释。大概说一下回帖人的意思是promise首先应该是一个异步流程控制的解决方案流程控制包括了正常的数据流和异常流程处理。而deferred的方式存在一个致命的缺陷就是promise链的第一个promisedeferred.promise的触发阶段抛出的异常是不交由promise自动处理的。我写几个demo解释下这句话 var Q require(q);var deferred Q.defer();deferred.promise.then(v {throw err }).catch(reason console.log(reason));  // errsetTimeout(() deferred.resolve(tarol));以上是一个正常的异常流程处理在值链中抛出了异常自动触发下一个promise的onRejected。但是如果在deferred.promise触发阶段的业务流程中抛出了异常呢 var Q require(q);var deferred Q.defer();deferred.promise.catch(reason console.log(reason));  // 不触发setTimeout(() {throw err;deferred.resolve(tarol); });这个异常将抛出到最外层而不是由promise进行流程控制如果想让promise处理抛出的异常必须这么写 var Q require(q);var deferred Q.defer();deferred.promise.catch(reason console.log(reason)); // errsetTimeout(() {try {throw err;} catch (e) {deferred.reject(e);} });deferred的问题就在这里了在deferred.promise触发阶段抛出的异常不会自动交由promise链进行控制。而es6的方式就简单了 var p new Promise(() {throw err; });p.catch(r console.log(r)); // err可见TC39在设计Promise接口时首先考虑的是将Promise看作一个异步流程控制的工具而非一个订阅发布的事件模块所以最终定下了new Promise(resolver)这样一种创建方式。   但是如果你说我不听我不听deferred就是比new Promise好而且我的promise在触发阶段是不会抛出异常的。那好还有另外一套标准满足你那就是Promises/B和Promises/D。其中Promises/D可以看做Promises/B的升级版就如同Promises/A之于Promises/A。这两个标准的撰写者都是同一个人就是上面Promises/A组织中圈起来的大胡子他不仅维护了这两个标准还写了一个实现库就是上面提到的Q同时angular中的$q也是参照Q实现的。   Promises/B和Promises/D以下统称为Promises/B都位于CommonJS社区但是由于没有被社区采用处于废弃的状态。而Q却是一个长期维护的类库所以Q的实现和两个标准已经有所脱离请知悉。   Promises/B和es6可以说是Promises/A的两个分支基于不同的设计理念在Promises/A的基础上设计了两套不同的promise规则。鉴于Promises/A在创建promise上的空白Promises/B同样提供了创建promise的方法而且是大量创建promise的方法。以下这些方法都由实现Promises/B的模块提供而不是Promises/B中promise对象的方法。 when(value, callback, errback_opt)类似于es6中Promise.resolve(value).then(callback, errback_opt)asap(value, callback, errback_opt)基本逻辑同when但是when中callback的调用会放在setTimeout(callback, 0)中而asap中callback是直接调用该接口在Q中已经废弃enqueue(task Function)将一个callback插入队列并执行其实就是fn setTimeout(fn, 0)该接口在Q中已经废弃get(object, name)类似于Promise.resolve(object[name])post(object, name, args)类似于Promise.resolve(object[name].apply(object, args))put(object, name, value)类似于Promise.resolve({then: resolve object[name] value; resolve()})该接口在Q中重命名为setdel(object, name)类似于Promise.resolve({then: resolve delete object[name]; resolve()})该接口在Q中alias为deletemakePromise创建一个流程控制类的promise并自定义其verbs方法verbs方法指以上的get、post、put、deldefer创建一个deferred包含一个延时类的promisereject创建一个rejected的流程控制类promiseref创建一个resolve的流程控制类promise该接口在Q中重命名为fulfillisPromise判断一个对象是否是promisemethod传入verbs返回对应的函数如method(get)即是上面4中的get已废弃  不知道以上API的应用场景和具体用法不要紧我们先总结一下。Promises/B和es6理念上最大的出入在于es6更多的把promise定义为一个异步流程控制的模块而Promises/B更多的把promise作为一个流程控制的模块。所以Promises/B在创建一个promise的时候可以选择使用makePromise创建一个纯粹的操作数据的流程控制的promise而get、post、put、del、reject、ref等都是通过调用makePromise实现的是makePromise的上层API也可以使用defer创建一个deferred包含promise这个属性对应一个延时类的promise。   延时类的promise经过前面的解释基本都了解用法和场景那对数据进行流程控制的promise呢在上面Promises/A部分说明了get和call两个API的用法和场景Promises/B的get对应的就是Promises/A的getcall对应的是post。put/set是Promises/B新增的和前二者一样在操作数据时进行流程控制。比如在严格模式下如果对象a的属性b的writable是false。这时对a.b赋值是会抛出异常的如果异常未被捕获那么会影响后续代码的运行。 use strict; var a {};Object.defineProperty(a, name, {value: tarol,writable: false });a.name okay;console.log(end);  // 不运行这时候如果使用Q的put进行流程控制就可以把赋值这部分独立开来不影响后续代码的运行。 use strict; var Q require(q);var a {};Object.defineProperty(a, name, {value: tarol,writable: false });Q.set(a, name, okay).then(() console.log(success),() console.log(fail)  // fail );console.log(end);  // end这部分的应用场景是否有价值呢答案就是见仁见智了好在Q还提供了makePromise这个底层API自定义promise可以实现比增删改查这些verbs更强大的功能。比如当我做数据校验的时候可以这样写 var Q require(q);var p Q.makePromise({isNumber: function(v) {if (isNaN(v)) {throw new Error(${v} is not a number);} else {return v;}} });p.dispatch(isNumber, [1a]).then(v console.log(number is ${v})).catch(err console.log(err, err));  // 1a is not a number p.dispatch(isNumber, [1]).then(v console.log(number is ${v}))  // number is 1.catch(err console.log(err, err));   以上不涉及任何异步操作只是用Q对某个业务功能做流程梳理而已。   而且Q并未和es6分家而是在后续的版本中兼容了es6的规范Q.Promise对应es6中的全局Promise成为了es6的父集加之Q也兼容了Promises/A中被A抛弃的部分如progressHandler、get、callpost。所以对于Q你可以理解为promise规范的集大成者整体来说是值得一用的。   最后要提到的是最为式微的promise规范——Promises/KISS它的实现库直接用futures命名实现了KrisZyp未竟的心愿。如果比较github上的starKISS甚至不如我没有提及的then.js和when。但是鉴于和Q一样是有一定实践经验后CommonJS社区promise规范的提案所以花少量的篇幅介绍一下。   Promises/KISS不将Promises/A作为子集所以它没有提供then作为订阅器代之的是when和whenever两个订阅器。触发器也不是常见的resolve、reject而是callback、errback和fulfill。其中callback类似于notify即progressHandler的触发器errback类似于rejectfulfill类似于resolve。   为什么会有两个订阅器呢因为KISS不像Promises/AA中的then中是传入三个监听器其中progressHandler还可以多次触发。但是KISS中的when和whenever一次只能传入一个监听器所以它要解决的是同一种订阅方式怎么订阅三种不同的监听器   首先怎么区分fulfilledHandler和errorHandler呢KISS借鉴了nodejs的回调函数方式第一个参数是err第二个参数是data。所以fulfilledHandler和errorHandler在一个监听器里这样进行区分 function(err, data) {if (err) {...} // errorHandlerelse {...} // fulfilledHandler }那怎么区分多次调用的progressHandler呢使用when注册的监听器只能调用一次使用whenever注册的监听器可以调用多次。我们写个demo区分Q和KISS的API的不同 var Q require(q); var defer Q.defer(); defer.promise.then(v console.log(fulfill, v),err console.log(reject, err),progress console.log(progress, progress) ); defer.notify(20);  // progress 20 defer.notify(30);  // progress 30 defer.notify(50);  // progress 50 defer.resolve(ok);  // fulfill okvar future require(future);var p new future(); var progressHandler function(err, progress) {if (err) {console.log(err, err);} else {console.log(progress, progress);} }; p.whenever(progressHandler); p.callback(20);  // progress 20 p.callback(30);  // progress 30 p.callback(50);  // progress 50 p.removeCallback(progressHandler);  // 需要移除监听器不然fulfill时也会触发 p.when(function(err, v) {   // 需要在callback调用后注册fulfill的监听器不然callback会触发if (err) {console.log(reject, err);} else {console.log(fulfill, v);} }); p.fulfill(void 0, ok);  // fulfill ok可见实现同样的需求使用future会更麻烦而且还存在先后顺序的陷阱我一向认为简单类库的应用代码如果存在严重的先后顺序是设计的不合格习惯使用es6的promise的童鞋还是不建议使用KISS标准的future。   整篇文章就到这里前面提到的then.js和when不再花篇幅介绍了。因为promise的实现大同小异都是订阅发布特定的流程控制只是各个标准的出发点和侧重点不同导致一些语法和接口的不同。而随着es标准的越来越完善其他promise的标准要么慢慢消亡如future、then.js要么给后续的es标准铺路如bluebird、Q。所以如果你没有什么执念的话乖乖的跟随es标准是最省事的做法。而这边随笔的目的一是借机整理一下自己使用各个promise库时长期存在的疑惑二是告诉自己很多现在看来尘埃落地的技术并非天生如此沿着前路走过来会比站在终点看到更精彩的世界。转载于:https://www.cnblogs.com/tarol/p/9042407.html
http://www.zqtcl.cn/news/800988/

相关文章:

  • 商城做网站家具网站模板
  • 国有企业网站建设网站悬浮qq
  • 上海建站宝盒微网站生成app
  • 做网站是什么时候分页有哪些制作网站的公司
  • 专业柳州网站建设哪家好5千ip的网站能赚多少钱
  • 网站开发代理最火网页游戏
  • 做网站运营工资多少网站建设协议需要注意的问题
  • 如何建设一个人工智能网站qq头像网站源码
  • 有什么网站可以做外贸出口信息泉州网站制作运营商专业
  • 创业seo快速排名优化公司
  • 安丘网站开发王野天 女演员
  • 沈阳软件公司 网站制作wordpress未验证邮箱用户
  • 做动画上传网站赚钱么杭州市网站建设公司
  • 网站建设注意细节问题微信二维码
  • 凡科做的网站提示证书错误网络营销渠道可分为哪几种
  • 南京手机网站制作公司免费设计房屋效果图软件有哪些
  • 定制类网站怎么样做网页设计
  • 企业门户网站建设优势网站登录模版
  • 六盘水建设网站徐州建站平台
  • 昆明有多少做网站的公司公司软文代写
  • 东莞模板网站做一个电子商务网站在哪里做
  • 给别人网站做跳转株洲专业网站排名优化
  • 国外网站空间租用费用网站前端设计图
  • 宜州做网站点点网 xml转wordpress
  • 太原建站方法erp系统好上手吗
  • 网站建设如何实现检索功能河南城乡建设网站
  • 江苏做电缆桥架的公司网站购物网站答辩ppt怎么做
  • 惠州网站建设系统公司公司网站建设公司
  • 做酒类直供网站行吗石家庄桥西网站制作公司
  • 电子商务门户网站的研究与实现漳州做网站多少钱