Promise 的实例状态变成 Resloved 或者 Rejected,就会触发 then 方法绑定的回调函数 提前解释一些方法或者钩子的含义 apply 、 call 、bind 三者的区别 apply 、 call 、bind 三者都是用来改变函数的 this 对象的指向的; apply 、 call 、bind 三者第一个参数都是 this 要指向的对象,也就是想指定的上下文; call …

Promise 的实例状态变成 Resloved 或者 Rejected,就会触发 then 方法绑定的回调函数

提前解释一些方法或者钩子的含义

apply 、 call 、bind 三者的区别

  1. apply 、 call 、bind 三者都是用来改变函数的 this 对象的指向的;
  2. apply 、 call 、bind 三者第一个参数都是 this 要指向的对象,也就是想指定的上下文;
  3. call 、bind 第一个参数后的参数是是给当前函数传的参数,apply 只有两个参数,第二个参数是以数组形式给当前函数传参数
  4. bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用

一些定义

  1. arguments.callee:正在执行的这个函数的引用
  2. arguments.callee.length:当前对象形参的个数
  3. arguments.length:当前对象实参的个数
  4. [].slice.apply(arguments),把类数组转成数组
  5. 严格模式,在严格模式下 arguments.callee(正在执行的这个函数的引用)无效

demo1:最简单实现

// 定义了三个promise,指定时间后状态变成Resolved,都执行下一个promise,直到第三个,第三个完成,递归
function t1() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, '绿灯');
  });
}
function t2() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 2000, '黄灯');
  });
}
function t3() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 3000, '红灯');
  });
}
(function restart() {
  t1().then((result) => {
    console.log(result);
  });
  t2().then((result) => {
    console.log(result);
  });
  t3().then((result) => {
    console.log(result);
    restart();
  });
})();

如果设定绿灯是 5000ms,黄灯是 2000ms,红灯是 3000ms,那么就会先显示黄灯,后显示红灯,显示绿灯的同时也会显示黄灯

因为第二轮绿灯 5000ms 包含了黄灯的 5000ms

demo2:较复杂的实现

// 定义了三个灯的Promise实例,每定义一个,都会延迟指定时间后把状态变成Resolved,直到最后一个,然后递归
function green() {
  return new Promise((resolve, reject) => {
    console.log(`绿灯:当前时间(${new Date().getSeconds()}s)`);
    resolve();
  });
}
function yellow() {
  return new Promise((resolve, reject) => {
    console.log(`黄灯:当前时间(${new Date().getSeconds()}s)`);
    resolve();
  });
}
function red() {
  return new Promise((resolve, reject) => {
    console.log(`红灯:当前时间(${new Date().getSeconds()}s)`);
    resolve();
  });
}
function ms_5000() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 5000);
  });
}
function ms_3000() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 3000);
  });
}
function ms_2000() {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, 2000);
  });
}
(function restart() {
  // 绿灯5000ms后转黄灯,黄灯3000ms后转红灯,红灯2000ms后,重复初始动作
  green()
    .then(ms_5000)
    .then(yellow)
    .then(ms_3000)
    .then(red)
    .then(ms_2000)
    // arguments.callee:正在执行的这个函数的引用
    .then(arguments.callee);
})();

demo3:demo2 的封装

// 第一个灯是一个Promise实例,状态先编程Resolved,然后,到过指定时间再变成Resolved,直到最后一个,然后递归
(function restart() {
  new Promise((resolve, reject) => {
    console.log(`绿灯:当前时间(${new Date().getSeconds()}s)`);
    resolve();
  })
    .then(() => {
      return new Promise((resolve, reject) => {
        setTimeout(resolve, 5000);
      });
    })
    .then(() => {
      return new Promise((resolve, reject) => {
        console.log(`黄灯:当前时间(${new Date().getSeconds()}s)`);
        resolve();
      });
    })
    .then(() => {
      return new Promise((resolve, reject) => {
        setTimeout(resolve, 3000);
      });
    })
    .then(() => {
      return new Promise((resolve, reject) => {
        console.log(`红灯:当前时间(${new Date().getSeconds()}s)`);
        resolve();
      });
    })
    .then(() => {
      return new Promise((resolve, reject) => {
        setTimeout(resolve, 2000);
      });
    })
    // arguments.callee:正在执行的这个函数的引用
    .then(arguments.callee);
})();

demo4:比较好的实现方式

// 使用严格模式,arguments.callee(正在执行的这个函数的引用)无效
// 定义了一个handle函数,用于return一个含有Promise实例的函数,指定时间把状态变成了Resolved,直到最后一个,然后递归
function handler(timer) {
  return function() {
    var arr = [].slice.apply(arguments);
    var that = this;
    return new Promise((resolve, reject) => {
      arr.unshift(resolve);
      // 相当于timer(arr[0],arr[1])
      timer.apply(that, arr);
    });
  };
}
(function restart() {
  'use strict';
  console.log(`绿灯:当前时间(${new Date().getSeconds()}s)`);
  handler(setTimeout)
    .bind(null, 5000)()
    .then(() => {
      console.log(`黄灯:当前时间(${new Date().getSeconds()}s)`);
      return handler(setTimeout).bind(null, 3000)();
    })
    .then(() => {
      console.log(`红灯:当前时间(${new Date().getSeconds()}s)`);
      return handler(setTimeout).bind(null, 2000)();
    })
    .then(() => {
      restart();
    });
})();

demo5:完美实现方式

// 避免了allpy和bind的使用,直接使用setTimeout,给handler传入延迟的时间,用户延迟多少ms后更改Promise状态至Resolved,直到最后一个,然后递归
function handler(ms) {
  return function() {
    return new Promise((resolve, reject) => {
      setTimeout(resolve, ms);
    });
  };
}
(function restart() {
  'use strict';
  console.log(`绿灯:当前时间(${new Date().getSeconds()}s)`);
  handler(5000)()
    .then(() => {
      console.log(`黄灯:当前时间(${new Date().getSeconds()}s)`);
      return handler(3000)();
    })
    .then(() => {
      console.log(`红灯:当前时间(${new Date().getSeconds()}s)`);
      return handler(2000)();
    })
    .then(() => {
      restart();
    });
})();

暂无评论