面试题:promise的链式怎么实现的
写文章为了让自己好记住知识点,也为了后续当作笔记来看待
前言
之前有过一次面试,面试官问 promise 相关的知识点,然后我回答了,他追问说 promise 的链式怎么实现?我当时没反应过来。面试官很有耐心,说 jquery 也是有链式的,你看过 jquery 的源码吗?它的链式怎么写的?我还是不知道,后来没通过面试,这个知识点常被我回忆,现在正好有时间,来写一写
正文
答案是:返回this
先来一个例子:
var person = {
  name: "johan",
  age: 28,
  sayName: function () {
    console.log("my name is" + this.name);
  },
  sayAge: function () {
    console.log("my age is " + this.age);
  },
};
命名一个对象,它有两个方法,sayName 和 sayAge ,如果我想这样表示 person.sayName().sayAge() 呢?怎么做,在方法 sayName 和 sayAge 中返回 this,即
var person = {
  name: "johan",
  age: 28,
  sayName: function () {
    console.log("my name is" + this.name);
    return this;
  },
  sayAge: function () {
    console.log("my age is " + this.age);
    return this;
  },
};
这就是表示,调用方法 sayName 、sayAge 后,返回调用者,即例子 person.sayName() ,person 调用 sayName,调用完后返回值还是 person。所以它可以继续链式调用 sayAge,因为它表示的还是 person
Promise 中的链式
Promise 本身没有链式,但是 Promise 的实例对象中的 then 有链式
function MyPromise(executor) {
}
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    return new Promise((resolve, reject) => {
        ...
    })
}
当你使用 Promise 时,一般是这样使用:
let promise = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000);
});
promise.then(() => {
  console.log("1s后显示");
});
如果加上链式
promise
  .then(() => {
    console.log("1s后显示,第一个");
  })
  .then(() => {
    console.log("1s后显示,第二个");
  });
所以很明显,每调用一次 then,就是返回一个实例对象(return new Promise )
Jquery 中的链式
源码太多内容,就拿 core.js 中的代码为例子
jQuery.fn = jQuery.prototype = {
  // The current version of jQuery being used
  jquery: version,
  constructor: jQuery,
  // The default length of a jQuery object is 0
  length: 0,
  toArray: function () {
    return slice.call(this);
  },
  // Get the Nth element in the matched element set OR
  // Get the whole matched element set as a clean array
  get: function (num) {
    // Return all the elements in a clean array
    if (num == null) {
      return slice.call(this);
    }
    // Return just the one element from the set
    return num < 0 ? this[num + this.length] : this[num];
  },
  // Take an array of elements and push it onto the stack
  // (returning the new matched element set)
  pushStack: function (elems) {
    // Build a new jQuery matched element set
    var ret = jQuery.merge(this.constructor(), elems);
    // Add the old object onto the stack (as a reference)
    ret.prevObject = this;
    // Return the newly-formed element set
    return ret;
  },
  // Execute a callback for every element in the matched set.
  each: function (callback) {
    return jQuery.each(this, callback);
  },
  map: function (callback) {
    return this.pushStack(
      jQuery.map(this, function (elem, i) {
        return callback.call(elem, i, elem);
      })
    );
  },
  slice: function () {
    return this.pushStack(slice.apply(this, arguments));
  },
  first: function () {
    return this.eq(0);
  },
  last: function () {
    return this.eq(-1);
  },
  even: function () {
    return this.pushStack(
      jQuery.grep(this, function (_elem, i) {
        return (i + 1) % 2;
      })
    );
  },
  odd: function () {
    return this.pushStack(
      jQuery.grep(this, function (_elem, i) {
        return i % 2;
      })
    );
  },
  eq: function (i) {
    var len = this.length,
      j = +i + (i < 0 ? len : 0);
    return this.pushStack(j >= 0 && j < len ? [this[j]] : []);
  },
  end: function () {
    return this.prevObject || this.constructor();
  },
};
我们不用看全部,但看其中的方法,是不是和最开始的例子很像——return this
所以链式不可怕,可怕的是,动都不动就自我劝退