美文网首页
异步处理:回调函数与promise

异步处理:回调函数与promise

作者: sweetBoy_9126 | 来源:发表于2019-01-03 23:37 被阅读51次

前置知识
回调可以是同步也可以是异步,异步必须放在回调里执行,也就是对于一个异步任务只有回调函数里的才是异步的,比如:

<ul>
  <li class="one">one</li>
  <li class="two">two</li>
  <li class="three">three</li>
</ul>
<script>
    {
      let view = {
        el: 'ul',
        selector: null,
        init(){
          this.$el = $(this.el)
        }
      }
      let model = {
        
      }
      let controller = {
        init(view, model){
          this.view = view
          this.model = model
          this.view.init()
          this.bindEvent()
        },
        find(){
          return this.view.$el.find(this.selector)
        },
        bindEvent(){
          this.selector = '.one'
          this.find().on('click',(e)=>{
            console.log(this.selector)
          })
          this.selector = '.two'
        },
        
      }
      controller.init(view,model)
    }
  </script>

上面的事件监听是异步任务,但也只是它的回调里是异步的,所以this.find()的时候是同步的this.selector是'.one',而(e)=>{console.log(this.selector)}这个回调里才是异步代码,所以等页面中所有的同步代码完成后才去执行的,也就是这时候的this.selector是'.two',也就是点击one的时候打印出.two

回调

把一个函数A传给另一个函数B调用,那么A就是回调函数
1.具名回调写法

function 获取用户信息(fn){
    fn.call(undefined,'姓名:王立发')
}
function 用户信息(信息){
    console.log(信息)
}
获取用户信息.call(undefined,用户信息)
//姓名:王立发
  1. 匿名回调写法
function 获取用户信息(fn){
    fn.call(undefined,'姓名:王立发')
}

获取用户信息.call(undefined,function(信息){
    console.log(信息)
})

3.多层嵌套的匿名回调(回调地狱)

获取用户信息(function(用户信息){
  console.log(用户信息)
  保存用户信息(用户信息, function(){
    获取另一个用户信息(function(另一个用户信息){
      保存用户信息(function(){})
    })
  })
})

像这种使用多层匿名函数回调的嵌套,就会很难让人读懂你的代码,而这种回调套回调(一般三到五层以上)又称为回调地狱

  1. 缺点
  1. 容易造成回调地狱
  2. 不知道该怎么使用回调Node/jQuery的回调使用方法都不一样--只能强行背下

promise

1.解决了不知道该如何使用回调问题
promise前面是操作,后面的then是操作的结果,then里面的第一个参数是成功后要做的,第二个是失败后要做的

获取用户信息().then(function(){},function(){})

2.解决了回调地狱
可以不断地then,就不存在嵌套了,永远只有一层

获取用户信息()
.then(打印用户信息)
.then(获取另一个用户信息)
.then(打印用户信息)

使用promise实现上面回调地狱中的案例

function 获取用户信息(){
    return new Promise((resolve,reject)=>{
        console.log('第一次获取用户信息')
        resolve('姓名:发发')
    })
}
function 打印用户信息(用户信息){
    return new Promise((resolve,reject)=>{
        console.log(用户信息)
        resolve()
    })
}
function 获取另一个用户信息(){
    return new Promise((resolve,reject)=>{
        console.log('第二次获取用户信息')
        resolve('姓名:琳琳')
    })
}
获取用户信息()
    .then(打印用户信息)
    .then(获取另一个用户信息)
    .then(打印用户信息)

//第一次获取用户信息
//姓名:发发
//第二次获取用户信息
//姓名:琳琳

.then里面的成功函数里面的第一个参数的值就是在resolve()里传入的实参

同样reject里面传入的实参也是then里面的失败函数里面的第一个参数的值

如果你不给resolve或者reject传值,那么你通过then里面传入参数拿到的就是undefined

案例

function 获取用户信息(name){
    return new Promise((resolve,reject)=>{
        if(name === '发发'){
            console.log('我认识发发')
            resolve('发发是一个帅锅')
        }else{
            console.log('不认识')
            reject()
        }
    })
}
获取用户信息('发发')
    .then(
        (res)=>console.log(res),
        (err)=>console.log('看来他不认识发发')
    )
//我认识发发
// 发发是一个帅锅

获取用户信息('琳琳')
    .then(
        (res)=>console.log(res),
        (err)=>console.log('看来他不认识发发')
    )
//不认识
// 看来他不认识发发

另外如果你想对一个值进行多次then操作,那么你就需要在每一个成功函数里面的resolve都传入参数,用来获取你上一次的值
比如:

function 获取用户信息(name){
    return new Promise((resolve,reject)=>{
        if(name === '发发'){
            console.log('我认识发发')
            resolve(['发发','是个帅锅'])
        }else{
            console.log('不认识')
            reject()
        }
    })
}
function 获取好友信息(name){
    return new Promise((resolve,reject)=>{
        if(name === '发发'){
            resolve('张三、李四、王五')
        }
        else{
            reject()
        }
    })
}
function 打印信息(data){
    return new Promise((resolve,reject)=>{
        console.log(data)
        resolve(data[0])
    })
}
获取用户信息('发发')
    .then(打印信息)
    .then(获取好友信息)
    .then(打印信息)
//我认识发发
// ["发发", "是个帅锅"]
// 张三、李四、王五

then里面的函数不管是调用了成功函数还是失败函数,它的下一个then都会执行成功的函数,除非你在失败函数里面直接reject。
比如:

function 获取用户信息(name){
    return new Promise((resolve,reject)=>{
        if(name === '发发'){
            console.log('我认识发发')
            resolve(['发发','是个帅锅'])
        }else{
            console.log('不认识')
            reject()
        }
    })
}
function 获取好友信息(name){
    console.log('获取好友信息')
    return new Promise((resolve,reject)=>{
        if(name === '发发'){
            resolve('张三、李四、王五')
        }
        else{
            reject()
        }
    })
}
function 打印信息(data){
    return new Promise((resolve,reject)=>{
        console.log(data)
        resolve(data[0])
    })
}
function 打印失败(理由){
    console.log('失败理由是'+理由)
}
获取用户信息('琳琳')
    .then(打印信息,打印失败)
    .then(获取好友信息)
    .then(打印信息)
//不认识
// 失败理由是undefined
// 获取好友信息

上面虽然调用了第一个then的失败函数,但是下一个的获取好友这个函数依然会执行,主要是因为我们失败函数里什么也没return,浏览器会默认为我们已经处理好了这个错误,但是我们该如何让浏览器知道我们没搞定这个失败,让下面的成功函数不执行哪?
方法:
1.直接在失败函数里返回一个promise然后调用reject

上面没有继续执行获取好友信息这一函数

  1. 直接return Promise.reject()

另外Promise()里面的代码都是同步的,只有then()里面的才是异步的

await

上面我们通过.then可以拿到成功或者失败的信息,但是then里面其实还是用了回调,有什么方法可以不使用回调哪?
方法:在返回promise的函数之前加一个await
比如:

let 用户信息 = await 获取用户信息('发发')
console.log(用户信息)
//["发发", "是个帅锅"]

上面的代码如果不加await拿到的就是一个new Promise(),加上await意思就是等它resolve,那么如果它失败了就会报错,所以我们需要配合try..catch来使用

正确写法

try{
  let 用户信息 = await 获取用户信息('琳琳')
  console.log(用户信息)
}catch(error){
  //失败的理由是
  console.log(error)
}

如果你想在一个函数里使用await那么就必须在这个函数前面加async

相关文章

  • ES6系列之Promise

    本篇目录 JS 同步与异步 常见异步处理回调函数事件监听Deferred对象 Promise对象概念 Promis...

  • nodejs--day4笔记

    1. 同步与异步API 回调函数 通过回调函数返回异步API的值 代码执行顺序 2. promise 解决回调...

  • 小程序中异步处理的几种方式对比

    异步处理方式 1.异步处理的几种方式 纯粹的异步回调函数callback promise方法 (async,awa...

  • 异步的实现

    异步的三种实现方式: 回调函数事件Promise 回调函数 回调函数不一定是异步 但是异步一定是回调函数。 事件 ...

  • 对promise的理解?

    Promise是解决异步编程的方案;promise是为解决异步处理回调金字塔问题而产生的 resolve函数的作用...

  • 个人笔记

    同步/异步 回调函数=> 回调地狱 setInterval/setTimeout =>Promise=>Gener...

  • 异步处理:回调函数与promise

    前置知识回调可以是同步也可以是异步,异步必须放在回调里执行,也就是对于一个异步任务只有回调函数里的才是异步的,比如...

  • Promise和async\await

    回调函数 用来处理异步问题,例如发送Ajax,setTimeout等 Promise 封装的例子 async\await

  • node 异步编程

    回调函数方式缺点:回调地狱、异步并发控制困难 Promise Async / Await

  • Promise解决回调嵌套问题及终极解决方案async 和 aw

    一、Promise 1.异步函数 与 回调函数的说明 回调函数:把一个函数当成参数传递, 将来特定的时机调用, 这...

网友评论

      本文标题:异步处理:回调函数与promise

      本文链接:https://www.haomeiwen.com/subject/kgzfrqtx.html