您的位置 首页 > 数码极客

es6class如何回调

说到 ES6,Promise 是绕不过的问题;如果说 ES6 的 Class 是基于 Javascript 原型继承的封装,那么 Promise 则是对 callback 回调机制的改进。这篇文章,不谈 Promise 的实际应用;聊一下 Promise 的实现原理,从最简单的解决方案入手,一步一步的自己实现一个 SimplePromise。

正文

从最简单的 Promise 初始化和使用入手:

const pro = new Promise ((res, rej) => {})

(data => {}, err => {})

Promise 的构造函数如上,需要传递一个函数作为参数,这个函数有两个变量: resolve, reject。而 Promise 有不同的执行状态,分三种情况:Resolve, Reject, Pending。根据以上的信息,写出最基本的 SimplePromise 的类结构:

class SimplePromise{

constructor(handler){

= "PENDING"

handler(this), (this))//参数函数的作用域指向Class

}

_resolve(){}

_reject(){}

}

接下来思考一下_resolve 与_reject两个函数的作用。我们知道,Promise 根据 then 方法来执行回调,而 then 是根据状态判断要执行的回调函数。不难推导出,_resolve 与_reject正是根据handler的执行来进行状态变更的,而状态只能由Pending向Reslove或Rejected转换,所以有:

class SimplePromise{

constructor(handler){

...

}

_resolve(val){//异步返回的数据

if( === "PENDING"){//保证状态的不可逆性

= "RESOLVED"

= val

}

}

_reject(val){

if( === "PENDING"){

= "REJECTED"

= val

}

}

}

then的调用逻辑

下面分析 then 函数的逻辑,从调用入手:

(data => {}, err => {})

then 接收两个参数,第一个是执行成功调用的函数,第二个是执行失败调用的函数。

class SimplePromise{

constructor(handler){

...

}

_resolve(val){

...

}

_reject(val){

...

}

then(success, fail){

switch (){

case "PENDING":

break;

case "RESOLVED":

success()

break;

case "REJECTED":

fail()

break;

}

}

}

以上实现了最简单的一个 Promise

测试代码:

const pro = new SimplePromise(function(res, rej) {

let random = Ma() * 10

if(random > 5){

res("success")

}

else{

rej("fail")

}

})

(function(data) {

con(data)

}, function(err) {

con(err)

})

当然,这不能算是一个 Promise,目前仅仅实现了根据状态调用不同的回调函数。还没有实现异步。

那如何实现异步呢?关键在于 then 函数,当判断_status为PENDING时,如何延后调用 success与fail函数,等待状态改变后再调用?

支持异步

这里采用数组来存储 fail 与 success 函数:

class SimplePromise{

constructor(handler){

= "PENDING"

= []//存储fail 与 success 函数

= []

handler(this), (this))

}

_resolve(val){

if( === "PENDING"){

...

let temp

while(.length > 0){//依次执行onSuccess中的回调函数

temp = .shift()

temp(val)

}

}

}

_reject(val){

if( === "PENDING"){

...

let temp

while(.length > 0){

temp = .shift()

temp(val)

}

}

}

then (success, fail){

switch (){

case "PENDING":

.push(success)

.push(fail)

break;

...

}

}

}

使用 onSuccess 和 onFail 来存储回调函数,当处理状态为 PENDING 时,将回调函数 push 到相应的数组里,当状态变更后,依次执行数组里的回调函数。

测试代码:

const pro = new SimplePromise(function(res, rej) {

setTimeout(function(){

let random = Ma() * 10

if(random > 5){

res("success")

}

else{

rej("fail")

}

}, 2000)

})

(function(data) {

con(data)

}, function(err) {

con(err)

})

两秒后,会执行相应的回调。

到目前为止,最最最简单的一个 Promise 骨架已经基本完成了。但是还有很多功能待完成。现在可以稍微休息一下,喝个咖啡打个鸡血,回来我们会继续让这个 Promise 骨架更加丰满起来。

. . . . . .

完善Promise

欢迎回来,下面我们继续完善我们的 Promise。

上面完成了一个最基础的 Promise,然而还远远不够。首先,Promise 需要实现链式调用,其次 Promise 还需要实现 all race resolve reject 等静态函数。

首先,如何实现 then 的链式调用呢?需要 then 返回的也是一个 Promise。

于是有

class SimplePromise{

...

then(success, fail){

RETURN new SimplePromise((nextSuccess, nextFail) => {

const onFullfil = function(val){

const res = success(val)

nextSuccess(res)

}

const onReject = function(val){

const res = fail(val)

nextSuccess(res) ;

}

switch (){

case "PENDING":

.push(onFullfil)

.push(onReject)

break;

case "RESOLVED":

onFullfil()

break;

case "REJECTED":

onReject()

break;

}

})

}

}

测试代码:

const sp = new SimplePromise(function (res, rej){

setTimeout(function(){

let random = Ma() * 10

random > 5 res(random) : rej(random)

}, 1000)

})

(data => {

con("more than 5 " + data)

return data

}, err =>{

con("less than 5 " + err)

return err

}).then((data) => {

con(data)

})

then的参数限制

完成了链式调用,then 方法还有许多其他限制:

下面思考 以下问题:代码中四个使用 promise 的语句之间的不同点在哪儿?

假设 doSomething 也 doSomethingElse 都返回 Promise

doSomething().then(function () {

return doSomethingElse();

}).then(finalHandler);

doSomething().then(function () {

doSomethingElse();

}).then(finalHandler);;

doSomething().then(doSomethingElse()).then(finalHandler);;

doSomething().then(doSomethingElse).then(finalHandler);;

答案 一会儿再揭晓,我们先来梳理以下then 方法对传入不同类型参数的处理机制:

直接上代码:

class SimplePromise{

...

then(success, fail){

return new SimplePromise((nextSuccess, nextFail) => {

const onFullfil = function(val){

if(typeof success !== "function"){

nextSuccess(val)

}

else{

const res = success(val)//success 的返回值

if(res instanceof SimplePromise){//如果success 返回一个promise 对象

res.then(nextSuccess, nextFail)

}

else{

nextSuccess(res)

}

}

}

if(fail){

const onReject = function(val){

if(typeof fail !== "function"){

nextSuccess(val)

}

else{

const res = fail(val)

if(res instanceof SimplePromise){

res.then(nextSuccess, nextFail)

}

else{

nextSuccess(res)

}

}

}

}

else{

onReject = function(){}

}

switch (){

case "PENDING":

.push(onFullfil)

.push(onReject)

break;

case "RESOLVED":

onFullfil()

break;

case "REJECTED":

onReject()

break;

}

})

}

}

对于传入 then 方法的参数,首先判断其是否为 function,判断为否,直接执行 下一个 then 的 success 函数;判断为是,接着判断函数的返回值 res 类型是否为 Promise,如果为否,直接执行下一个 then 的 success 函数,如果为是,通过 then 调用接下来的函数。

所以,上面的问题就不难得到答案了。

<!-- 1 -->

doSomething().then(function () {

return doSomethingElse();//返回值为Promise

}).then(finalHandler);

RETURN:

doSomething

--->doSomethingElse(undefined)

---> final(doSomethingElseResult)

<!-- 2 -->

doSomething().then(function () {

doSomethingElse();//返回值为 undefined

}).then(finalHandler);

RETURN:

doSomething

--->doSomethingElse(undefined)

---> final(undefined)

<!-- 3 -->

doSomething().then(doSomethingElse())//参数 typeof != function

.then(finalHandler);

RETURN:

doSomething

doSomethingElse(undefined)

---> final(doSomethingResult)

<!-- 4 -->

doSomething().then(doSomethingElse)//与1的调用方式是不同的

.then(finalHandler);

RETURN:

doSomething

--->doSomethingElse(doSomethingResult)

---> final(doSomethingElseResult)

好,then 方法已经完善好了。

静态函数

接下来是 Promise 的各种静态函数

class SimplePromise(){

...

static all(){}

static race(){}

static resolve(){}

static reject(){}

}

all

static all(promiselist){

i(promiselist)){

const len = ;

const count = 0

const arr = []

return new SimplePromise((res, rej) => {

for(let i = 0; i<len; data=""> {

arr[i] = data

count ++

if(count === len){//每一个Promise都执行完毕后返回

res(arr)

}

}, err => {

rej(err)

})

}

})

}

}</len;>

race

static race(promiselist){

i(promiselist)){

const len =

return new SimplePromise((res, rej) =>{

(item =>{

(item).then(data => {

res(data)

}, err =>{

rej(err)

})

})

})

}

}

resolve

static resolve(obj){

if(obj instanceof SimplePromise){

return obj

}

else {

return new SimplePromise((res) =>{

res(obj)

})

}

}

reject

static reject(obj){

if(obj instanceof SimplePromise){

return obj

}

else {

return new SimplePromise((res, rej) =>{

rej(obj)

})

}

}

总结

现在,一个完整的 Promise 对象就完成了。现在来总结一下 callback 回调和 Promise 的异同吧。

其实,不管是 callback 还是 Promise,这二者都是将需要滞后执行方法而提前声明的方式,只不过 callback 的处理方式比较粗犷,将 cb 函数放到异步执行的结尾;而 Promise 优于 cb 的是通过定义了不同的执行状态,更加细致的进行结果处理,提供了很好的 catch 机制,这是其一;其二,then 的链式调用解决了 cb 的回调地狱;但是 then 的链式调用也不是很好的解决方案,如果封装不好,then里面套用大量的代码的话也会引起代码的不美观和阅读上的困难,这一方面的终极解决方法还是 es7 的 async/await。

责任编辑: 鲁达

1.内容基于多重复合算法人工智能语言模型创作,旨在以深度学习研究为目的传播信息知识,内容观点与本网站无关,反馈举报请
2.仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证;
3.本站属于非营利性站点无毒无广告,请读者放心使用!

“es6class如何回调”边界阅读