你真的了解 Promise 吗?Promise 必知必会(十道题)入门教程_Promise小白帮助

Promise 想必大家十分熟悉,想想就那么几个 api,可是你真的了解 Promise 吗?本文根据 Promise 的一些知识点总结了十道题,看看你能做对几道。以下 promise 均指代 Promise 实例。题目一const promise = new Promise((resolve, reject) => {console.log(1)resol

你真的了解 Promise 吗?Promise 必知必会(十道题)入门教程

题目一

const promise = new Promise((resolve, reject) => {
  console.log(1)
  resolve()
  console.log(2)
})
promise.then(() => {
  console.log(3)
})
console.log(4)

运行结果:

你真的了解 Promise 吗?Promise 必知必会(十道题)入门教程_Promise小白帮助

1
2
4
3

解释:Promise 构造函数是同步执行的,promise.then 中的函数是异步执行的。

题目二

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
console.log(promise)
promise
  .then(() => {
    console.log(promise)
    throw new Error('error!!!')
  })
  .catch(err => {
    console.log(promise)
  })

运行结果:

Promise {  }
Promise { 'success' }
Promise { 'success' }

解释:promise 有 3 种状态:pending、fulfilled 和 rejected。状态改变只能是 pending->fulfilled 或者 pending->rejected,状态一旦改变则不能再变。

题目三

const promise = new Promise((resolve, reject) => {
  resolve('success1')
  reject('error')
  resolve('success2')
})

promise
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

运行结果:

then: success1

解释:构造函数中的 resolve 或 reject 只有第一次执行有效,多次调用没有任何作用,呼应代码二结论:promise 状态一旦改变则不能再变。

题目四

Promise.resolve(1)
  .then((res) => {
    console.log(res)
    return 2
  })
  .catch((err) => {
    return 3
  })
  .then((res) => {
    console.log(res)
  })

运行结果:

1
2

解释:promise 可以链式调用。提起链式调用我们通常会想到通过 return this 实现,不过 Promise 并不是这样实现的。promise 每次调用 .then 或者 .catch 都会返回一个新的 promise,从而实现了链式调用。

题目五

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('once')
    resolve('success')
  }, 1000)
})

const start = Date.now()
promise.then((res) => {
  console.log(res, Date.now() - start)
})
promise.then((res) => {
  console.log(res, Date.now() - start)
})

运行结果:

once
success 1005
success 1007

解释:promise 的 .then 或者 .catch 可以被调用多次,但这里 Promise 构造函数只执行一次。或者说 promise 内部状态一经改变,并且有了一个值,那么后续每次调用 .then 或者 .catch 都会直接拿到该值。

题目六

Promise.resolve()
  .then(() => {
    return new Error('error!!!')
  })
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

运行结果:

then: Error: error!!!
    at Promise.resolve.then (...)
    at ...

解释:.then 或者 .catch 中 return 一个 error 对象并不会抛出错误,所以不会被后续的 .catch 捕获,需要改成其中一种:

  1. return Promise.reject(new Error(‘error!!!’))
  2. throw new Error(‘error!!!’)

因为返回任意一个非 promise 的值都会被包裹成 promise 对象,即 return new Error(‘error!!!’) 等价于 return Promise.resolve(new Error(‘error!!!’))。

题目七

const promise = Promise.resolve()
  .then(() => {
    return promise
  })
promise.catch(console.error)

运行结果:

TypeError: Chaining cycle detected for promise #
    at 
    at process._tickCallback (internal/process/next_tick.js:188:7)
    at Function.Module.runMain (module.js:667:11)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:607:3

解释:.then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环。类似于:

process.nextTick(function tick () {
  console.log('tick')
  process.nextTick(tick)
})

题目八

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)

运行结果:

1

解释:.then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。

题目九

Promise.resolve()
  .then(function success (res) {
    throw new Error('error')
  }, function fail1 (e) {
    console.error('fail1: ', e)
  })
  .catch(function fail2 (e) {
    console.error('fail2: ', e)
  })

运行结果:

fail2: Error: error
    at success (...)
    at ...

解释:.then 可以接收两个参数,第一个是处理成功的函数,第二个是处理错误的函数。.catch 是 .then 第二个参数的简便写法,但是它们用法上有一点需要注意:.then 的第二个处理错误的函数捕获不了第一个处理成功的函数抛出的错误,而后续的 .catch 可以捕获之前的错误。当然以下代码也可以:

Promise.resolve()
  .then(function success1 (res) {
    throw new Error('error')
  }, function fail1 (e) {
    console.error('fail1: ', e)
  })
  .then(function success2 (res) {
  }, function fail2 (e) {
    console.error('fail2: ', e)
  })

题目十

process.nextTick(() => {
  console.log('nextTick')
})
Promise.resolve()
  .then(() => {
    console.log('then')
  })
setImmediate(() => {
  console.log('setImmediate')
})
console.log('end')

运行结果:

end
nextTick
then
setImmediate

解释:process.nextTick 和 promise.then 都属于 microtasks,而 setImmediate 属于 macrotasks,在事件循环的 check 阶段执行。事件循环的每个阶段(macrotasks)之间都会执行 microtasks,事件循环的开始会先执行一次 microtasks。

海计划公众号
(0)
上一篇 2020/04/06 04:10
下一篇 2020/04/06 04:10

您可能感兴趣的内容

  • TypeScript 2.0 标记联合类型菜鸟攻略_类型入门基础教程

    TypeScript 2.0 实现了一个相当有用的功能:标记联合类型,您可能将其称为 sum 类型或与其他编程语言区别开的联合类型。 标记联合类型是其成员类型都定义了字面量类型的区分属性的联合类型。上面的讲的是理论性的,来几个例子看看更贴切。使用标记的联合类型构建付款方式假设咱们为系统用户可以选择的以下支付方式建模Cash (现金)PayPal 与给定的电子

    2020/03/23
  • Js递归基础指南_递归入门指南

    传统的递归思想:自已调用自已,但是调用栈里面的执行上下文会越来越多,容易暴栈。采用尾递归可以规避这个问题:每次入栈出栈再入栈尾调用// 尾调用
    function f(x){return g(x);
    }// 伪代码
    ECStack.push( functionContext);ECStack.pop();ECStack.push( function

    2020/03/20
  • 用什么工具保证一致的代码风格?菜鸟攻略_代码菜鸟知识

    1. 理解问题首先这个问题展开来讲就是”如何在Node.js模块编写中保持代码一致性风格”。目前来说基本上有四种工具可以完成JSLint,JSHint,JSCS,ESLint。下面将从历史的角度来看看他们四个有什么关系,以及选用建议。2. 发展历程关于保持代码一致性风格,我们可以追溯到Lint。Lint是啥?Lint是针对C语言源码的检测工具,它的功能就是看

    2020/03/30
  • 使用Rollup打包并发布到npm使用指南_Rollup小白入门

    前言其实用 webpack 也可以打包库,不过根据create-react-app项目贡献者的说法:rollup适合发布 js 库,而webpack更适合做应用程序。简而言之就是:rollup 打包 js 比 webpack 方便,而 webpack 打包 css 比 rollup 方便,相信大家已经有所了解了,至于选用哪个相信大家已经清楚了,下面我们来详细

    2020/03/29
  • CSS3中的box-sizing(content-box与border-box)指南教程_盒子小白攻略

    CSS3中的box-sizing 属性允许以特定的方式来指定盒模型,有两种方式:content-box:标准盒模型,又叫做 W3C盒模型,一般在现代浏览器中使用的都是这个盒模型border-box:怪异盒模型,低版本IE浏览器中的盒模型 现代浏览器和IE9+默认值是content-box。
    语法格式:box-sizing:content-box | bo

    2020/03/30
  • 精读《如何做好 CodeReview》使用帮助_Review菜鸟教程下载

    精读《如何做好 CodeReview》使用帮助 1 引言 任何软件都是协同开发的,所以 CodeReview 非常重要,它可以帮助你减少代码质量问题,提高开发效率,提升稳定性,同时…

    2020/03/20
  • 什么是单点登录?入门基础知识_登录基础知识教程

    在日常工作中,用户需要访问大量的信息资源,例如,用户首先要登录到操作系统中,然后进入各个应用系统。进入每一个系统都需要对用户的身份进行识别与验证,这样,用户需要提供多个用户帐号与口令,为了便于记忆,用户很可能把各种帐号与口令信息记录在笔记本上,甚至写在便条上并贴在办公桌或屏幕边,这就使口令信息很容易泄露出去,增加了组织信息系统被入侵的安全风险。为了解决这个问

    2020/03/26
  • GraphiQL小白入门_在浏览器IDE中浏览 GraphQL

    GraphiQL小白入门 GitHub:https://github.com/graphql/graphiql 简介描述:在浏览器IDE中浏览 GraphQL 使用 node.js…

    2020/03/07
  • Fusioncharts基础教程一个免费版本,功能依然强大,图形类型依然丰富的图表图形类库

    Fusioncharts基础入门 官方网址:https://www.fusioncharts.com/ 简介描述:一个免费版本,功能依然强大,图形类型依然丰富的图表图形类库 很牛X…

    2020/03/05
  • Vue – 自定义组件双向绑定小白攻略_双向绑定指南攻略

    前言无论在任何的语言或框架中,我们都提倡代码的复用性。对于Vue来说也是如此,相同的代码逻辑会被封装成组件,除了复用之外,更重要的是统一管理提高开发效率。我真就接手过一个项目,多个页面都会用到的列表,没有去封装列表组件,只要有一点改动,每个页面都得加上。很肯定的说,没有用组件化开发的Vue项目是没有灵魂的。所以如何封装一个优雅且复用性高的组件成为我们必需的技

    2020/03/20
  • 网易云课堂使用攻略在网易云课堂前端开发频道,发现好课!

    网易云课堂基础入门 官方网址:http://study.163.com/category/front-end-development 简介描述:在网易云课堂前端开发频道,发现好课!

    2020/03/05
  • Linux 中的常见锁及其基本原理菜鸟攻略_Linux小白攻略

    0.概述通过本文将了解到如下内容:Linux系统的并行性特征互斥和同步机制Linux中常用锁的基本特性互斥锁和条件变量1.Linux的并行性特征Linux作为典型的多用户、多任务、抢占式内核调度的操作系统,为了提高并行处理能力,无论在内核层面还是在用户层面都需要特殊的机制来确保任务的正确性和系统的稳定运行,就如同一个国家需要各种法律条款来约束每个公民的行为,

    2020/03/23
  • Js事件循环机制 Event loop小白知识_事件入门基础知识

    前言1、队列的特征先进先出2、js是单线程的,任务都是排队执行,不会同步执行对个任务3、js分为同步(赋值,循环,分支语句)和异步(ajax,dom事件,定时器)4、事件循环机制js执行引擎的主线程,从任务队列获取任务,如果是异步任务,那么运行到异步任务时候,异步任务就退出主线程,主线程进行下一个任务的获取处理,如果是异步任务完成,就插入到任务队列的末尾,等

    2020/03/24
  • arthas基础入门_Alibaba开源的Java诊断工具

    arthas基础入门 官方网址:https://alibaba.github.io/arthas/ GitHub:https://github.com/alibaba/arthas…

    2020/03/06
  • peity.js小白指南_基于jquery渐进的 <SVG> 饼图,圆环图,条形图和折线图

    peity.js小白指南 官方网址:http://benpickles.github.io/peity GitHub:https://github.com/benpickles/p…

    2020/03/06
  • jquery.validate验证教程视频_插件基础知识教程

    jquery validate插件为表单提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求。该插件捆绑了一套有用的验证方法,包括 URL 和电子邮件验证,同时提供了一个用来编写用户自定义方法的 API。所有的捆绑方法默认使用英语作为错误信息,且已翻译成其他 37 种语言。规则名称类型描述requiredBoole

    2020/03/20