为什么面试总会问promise

171 阅读3分钟

随着node在前端的地位越来越高。大量的求职者总会随笔一下:

熟悉Node.js开发

ok。到这里,面试官便发问了:

  1. 什么是promise?
  2. promise是如何捕获异常的 ...

为什么promise是必不可少的呢?

回答这个问题前,我不知道大家是否有疑问?

Node是前端语言还是后端语言?

为什么会有这种疑问呢?

其实因为大多数的开发者其实或多或少的总会有node打交道,心底上认为这是一种前端语言

其实区分node是否是前端语言,很简单,只要记住这点就可以了

你主要用node去干什么?

你用node去构建工程,那node就是前端语言

你用node去做后台开发,那node就是后端语言

一般而言,node更像后端语言,无论是写法,还是思维方式更接近于后端。而此时就突出Promise的重要性了?

下面让我们去总结一下promise的几个知识点吧,让所有的求职者求职必过,心有所属。

promise对象及实例

1、 什么是promise

Promise是一个对象,从它可以获取异步操作的结果。Promise提供统一的API,各种异步操作都可以用相同的方式进行处理

2、Promise对象的特点是什么

Promise对象有两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果

3、Promise实例

 const promsie = new Promise((resolve, reject)=>{
    // code...
    if (/* 异步操作成功 */){
        resolve(value)
    } else {
        reject(value)
    }
})

promise.then(function (value) {
        // success
    }, function (error) {
        // failure
    });

4、手写一个promise实例

function timeout(ms) {
    return new Promise((resove, reject)=>{
        console.log("ok")
        setTimeout(() => {
            resove('done')
        }, ms);
    })
}

timeout(5000)
    .then((value)=>{
        console.log(value)
    })
    .catch((error)=>{
        console.log(error)
    })

原型和原型链

1.原型

Promise 实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的

2.原型链

then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function (comments) {
  console.log("resolved: ", comments);
}, function (err){
  console.log("rejected: ", err);
});

promise的API

  1. promise.prototype.then()
  2. promise.prototype.catch()
  3. promise.prototype.finally()
  4. promise.all()
  5. promise.race()
  6. promise.allSettled()
  7. promise.any()
  8. promise.resolve()
  9. promise.reject()

async

什么是async

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。

async例子

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world', 50);

由于async函数返回的是 Promise 对象,可以作为await命令的参数。所以,上面的例子也可以写成下面的形式。

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world', 50);

async的实现原理

async 函数的实现原理,就是将 Generator 函数和自动执行器,包装在一个函数里。

async function fn(args) {
  // ...
}

// 等同于

function fn(args) {
  return spawn(function* () {
    // ...
  });
}
function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {
      let next;
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
        step(function() { return gen.next(v); });
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}

async与promise代码比较

Promise 的写法如下。

function logInOrder(urls) {
  // 远程读取所有URL
  const textPromises = urls.map(url => {
    return fetch(url).then(response => response.text());
  });

  // 按次序输出
  textPromises.reduce((chain, textPromise) => {
    return chain.then(() => textPromise)
      .then(text => console.log(text));
  }, Promise.resolve());
}

aysnc 的写法如下

async function logInOrder(urls) {
  // 并发读取远程URL
  const textPromises = urls.map(async url => {
    const response = await fetch(url);
    return response.text();
  });

  // 按次序输出
  for (const textPromise of textPromises) {
    console.log(await textPromise);
  }
}

Promise的这种写法不太直观,可读性比较差

总结

Promise是一个不错异步操作解决方案,他解决了传统的通过回调和事件来解决异步操作的诸多问题,如“竞争”,回调信任度低的问题。

最后祝愿各位求职者心想事成,虎虎生威!