回调地狱挖坑 - Promise

一、promise()

promise方法是专门用于解决异步回调问题的方法,在ES6和ES7语法中得到使用,promise实例对象中可以传回调函数,此函数有两个参数:resolve和rejects,如果一步操作成功,则通过resolve把数据传出去,如果失败,则通过rejdects把错误信息传出去
Tips
1.promise函数必须通过then来获取数据
resolve函数的作用是,将promise对象的状态从“pending”变为‘’resolved‘’,在异步操作成功时调用,并将异步操作的结果,作为参数传递出去
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去
Promise构造的实例中可以传入一个回调函数,可以在这个回调函数里面执行异步操作,异步操作返回的结果通过resolve和reject传递出去,返回的是一个Promise对象,返回的参数需要该对象通过then函数获取到
下面我们演示一下:
我们通过计时器模拟异步加载来执行一些函数,正常情况如下:

function Test() {
    setTimeout(function () {
      let name = "测试"
      return name
    },1000)
  }
  function Test2() {
    let name = Test()
    console.log(name)  => // undefined
  }
  Test2()

Test()里面执行了一个异步操作,正常Test2()执行时,Test的数据还没有返回,所以name是undefined
使用Promise()来执行一下看下结果:

let Eat = new Promise(resolve => {
    setTimeout(function () {
      let name = "测试"
      resolve(name)
    }, 1000)
  })
function Test2() {
    Eat.then(res => {
      console.log(res) => // 测试
    })
  }
Test2()

可以看出Promise会等异步操作完成后,才会执行下一步操作
现在总体测试一下:

function first () {
    setTimeout(function () {
      console.log('这是第一步操作')
    },4000)
  }
  function second () {
    setTimeout(function () {
      console.log('这是第二步操作')
    },3000)
  }
  function third () {
    setTimeout(function () {
      console.log('这是第三步操作')
    },2000)
  }
  function fourth () {
    setTimeout(function () {
      console.log('这是第四步操作')
    },1000)
  }
  first()
  second()
  third()
  fourth()

// 输出结果

这是第四步操作
这是第三步操作
这是第二步操作
这是第一步操作

看同步操作,即使first先执行,但是结果却是最后打印,fourth是最后执行,但结果却是最先打印
现在来看看改成promise后的结果:

function first () {
    return new Promise(resolve => {
      setTimeout(function () {
        resolve('这是第一步操作')
      },4000)
    })
  }
  function second () {
    return new Promise(resolve => {
      setTimeout(function () {
        resolve('这是第二步操作')
      },3000)
    })
  }
  function third () {
    return new Promise(resolve => {
      setTimeout(function () {
        resolve('这是第三步操作')
      },2000)
    })
  }
  function fourth () {
    return new Promise(resolve => {
      setTimeout(function () {
        resolve('这是第四步操作')
      },1000)
    })
  }
  first()
    .then(res => {
      console.log(res)
      return second()
    })
    .then(res => {
      console.log(res)
      return third()
    })
    .then(res => {
      console.log(res)
      return fourth()
    })
    .then(res => {
      console.log(res)
    })

输出结果:

二、Promise方法

resolve() => // 传递异步成功时的数据
reject() => // 传递异步错误时的数据
then() => // 返回异步成功的数据作为参数
catch() => // 返回异步错误时的数据作为参数

function Test() {
    let promise = new Promise({
        if (success) {
            resolve(success)
        } else {
            reject(err)
        }
    })
    return promise
}

Test()
    .then(res => {
        console.log(res)
    })
    .catch(err => {
        console.log(err)
    })

all

Promise的all方法提供了一个能够同时并行处理所以异步操作函数的能力,更加精简了代码,并且在所有异步操作执行完后才执行then回调,我们再次执行上面四个函数试试:

Promise
    .all([first(),second(),third(),fourth()])
    .then(res => {
      console.log(res)
    })

结果展示:

从上面执行结果来看,all方法接收一个数组参数,数组里面的值都是返回的Promise对象,到了then方法里面,all方法会把所有异步操作resolve的结果保存在一个数组里传给then

race

all方法是谁返回结果最慢,就先执行谁,而race确恰恰相反,race方法是谁返回结果最快,我就先执行谁,至于执行的表达式跟all方法完全没有区别

Promise
    .race([first(),second(),third(),fourth()])
    .then(res => {
      console.log(res)
    })

执行结果展示:

看到结果,感觉不对,只打印了执行最快的那个异步操作的resolve,并没有打印其他三个的数据,但事实上四个都已经执行了
个人理解回到all,是并行执行完成后执行then回调,而all是以最慢的执行为先,也就是其它快的相当于推迟几秒返回结果,其实是已经执行完了,然后一起完成执行then回调,而race是以最快的执行为先,一秒第四步就完成了,后面虽然执行了,但是then已经执行了,所以resolve也就没有作用了。

posted @ 2019-04-03 15:40  不会代码的前端  阅读(218)  评论(0编辑  收藏  举报