学习Promise-1

212 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第3天,点击查看活动详情

image.png

前端开发同步异步的区别

  • 同步:一般指的是在代码运行的过程中,从上到下逐步运行代码,每一部分代码运行完成之后,下面的代码才能开始运行
  • 异步:指的是当我们需要一些代码在执行的时候不会影响其他代码的执行,也就是在执行代码的同时,可以进行其他的代码的执行,不用等待代码执行完成之后才执行之后的代码,就像我们人一样,可以一边看电视剧一边吃东西一样,互不干扰,这种方式就是异步。

而在前端开发中常见的异步一般常见的包括:setTimeout,setInterval,ajax。

  • setTimeout是定时延时运行函数,只执行一次

  • setInterval也是定时延时函数,但是这个函数本身可以一直执行,不会停止,除非把它清除。

  • ajax是前端常用的和后台进行异步交互数据的请求方式,其实它本身也包括同步和异步,同步的就是由代码从上到下顺序执行,而异步的ajax是我们发送请求到服务器之后,只需要在监听服务器的响应即可,不用等到请求结束在执行其他的代码,这就是异步ajax。

Promise 的含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和强大

所谓Promise,从语法上说,Promise是一个对象,从它可以获取异步操作的消息。简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。

Promise 的三种状态

(敲黑板!记住!这三种状态,考试要考的)
  • pending(进行时)
  • fulfilled(已成功)
  • rejected(已失败)

Promise 的两个特点

  • 对象的状态不受外界影响:

    Promise对象代表一个异步操作。对于三种状态,只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。Promise(承诺)的由来

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

    Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。

(特别说明:为了我瞎扯下文的方便后面的resolved统一只指fulfilled状态,不包含rejected状态。)

Promise API

(有点多,耐心看,挑重点)

Promise.resolve()

有时需要将现有对象转化为 Promise 对象,Promise.resolve()方法就起了这个作用

将状态从pending转化为fulfilled

Promise.resolve 方法的参数分成四种情况:

  • 参数是一个Promise实例

如果参数是一个 Promise 实例,那么 Promise.resolve 将不做任何修改,原封不动地返回这个实例。

  • 参数是一个thenable对象

thenable对象指的是具有then方法的对象,实例如下:

let thenable = {
    then:function(resolve,reject) {
        resolve(666)
    }
}

Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。

 1.   let thenable = {
 2.   then: function(resolve, reject) {
 3.   resolve(666);
 4.    }
 5.   };
 6.   let p1 = Promise.resolve(thenable); 
 7.   p1.then(function(value) {
 8.    console.log(value); // 666 
 9.      });

上面代码中,第6行代码执行完,对象p1的状态就变为 resolved,从而立即执行最后那个then方法指定的回调函数,输出 666

  • 参数不是具有 then 方法的对象,或者压根就不是对象

如果参数是一个原始值。也就是说参数是“hello world”,"1","2"....这种原始值,或者说不像上面所说的是一个不具有then方法的对象,则方法返回的是一个新的Promise对象,但是!状态已经发生了改变,变成了resolved,例子如下:

const p = Promise.resolve('小鳄鱼加油!');

p.then(function() {
        ....
    })
【特殊说明:判断参数内的玩意儿(对象)属不属于异步操作的方法是: 其具不具备 then 方法】

由于上面的字符串小鳄鱼加油!不属于异步操作,返回最新的Promise实例的状态从一生成就是resolved回调函数会立即执行。Promise.resolve方法的参数,会同时传给回调函数

  • 不带有任何参数

Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的 Promise 对象。

这是一个很方便快速得到一个 Promise 对象的方法

resolve()的注意点

话不多说直接上代码!

setTimeout(function() {
    console.log('3')
})

Promise.resolve().then(function() {
    console.log('2')
})

console.log('1')

// 1
// 2
// 3

上面代码中,setTimeout(fn, 0)在下一轮“事件循环”开始时执行,Promise.resolve()在本轮“事件循环”结束时执行,console.log('one')则是立即执行,因此最先输出。

Promise.reject()

将状态从pending转化为rejected

Promise.reject(reason)方法与上述的Promise.resolve()相同,也会返回一个新的 Promise 实例,该实例的状态为rejected

const p = Promise.reject('出错了!')

p.then(null.function(s) {
    console.log(s) // 出错了
})

上面代码生成一个 Promise 对象的实例p,状态为rejected,回调函数会立即执行。

注意:Promise.reject("猫南北"),里面的 ‘猫南北’ 会原封不动地作为reject的理由,这玩意会变成后续方法的参数。

这一点与 Promise.resolves方法是不一致的

看下面的代码就知道了

const thenable = {
    then(resolve,reject) {
        reject('猫南北')
    }
}
Promise.reject(thenable).catch(e => {
    console.log(e === thenable)
  })
  // true 

上面代码中,Promise.reject方法的参数是一个thenable对象,执行以后,后面catch方法的参数不是reject抛出的“猫南北”这个字符串,而是thenable对象。

应用

  • 加载图片
  • Generator 函数与 Promise 的结合

待续...