对于Promise的学习

news/2024/7/10 22:43:26 标签: javascript, es6, vue.js, 前端

对于Promise的学习

1.什么是Promise

简单来说Promise是异步编程的一种解决方案
Promise是ES6中的特性。
什么是异步操作?
网络请求中,对端服务器处理需要时间,信息传递过程需要时间,不像我们本地调用算术函数一样,这里的网络请求不是同步的有时延, 不能立即得到结果。
== 如何处理异步事件?==
对于网络请求这种,一般会使用回调函数,在服务器端传给我数据成功后,调用回调函数。例如Ajax调用。

javascript">$.ajax({
sucess:function(){
       ...
}
})

如果碰到嵌套网络请求,例如第一次网络请求成功后回调函数再次发送网络请求,这种代码就会让人含难受。

javascript">$.ajax({
sucess:function(){
       $.ajax({
       ...
       })
}
})

如果还需要再次的网络请求,那么又要嵌套一层,这样的代码层次不分明很难读,也容易出问题。

2.Promise的基本使用

什么时候使用Promise

解决异步请求冗余这样的问题,promise就是这样封装移步请求的。

Promise对象

javascript">new Promise((resolve, reject) => 
{})

Promise对象的参数是一个函数(resolve,reject) => {},这个函数又有两个参数分别是resolve和reject。这两个参数本身也是函数,后面还有回调函数then(func)的参数也是一个函数。
模拟定时器的异步事件
用定时器模拟网络请求,定时一秒为网络请求事件,用console.log()表示需要执行的代码。

javascript">//1.使用setTimeout模拟嵌套的第三次网络请求
setTimeout(() => {
//第一次请求
console.log("hello wk")
//第一次处理代码
setTimeout(() => {
//第二次请求
console.log("hello meng")
//第二次处理代码
setTimeout(() => {
//第三次请求
console.log("hello vue")
//第三次处理代码
        },1000)
      },1000)
   },1000)

一层套一层,看起来是不是很绕。
使用promise来处理异步操作

javascript">//参数  -> 函数
// resolve和reject本身也是函数
//then()的参数也是一个函数
new Promise((reslove,reject) => {
        setTimeout(() => {
        //第一次网络请求
        resolve(},1000)
     }).then(() => {
     console.log("hello wk")
     //第一次处理代码
     return new promise((resolve, reject) => {
     setTimeout(() => {
     //第二次网络请求
             resolve()
          },1000).then(() =>  {
            console.log("hello vuejs")//第二次处理代码
            return new Promise((resolve, reject) => {
                setTimeout(() => {//第三次网络请求
                    resolve()
                }, 1000)
            }).then(() => {
                console.log("hello java")//第三次处理代码
            })
        })
    })
})

是不是觉得代码还要更复杂了?仔细看看第一个如果使用了多个就找不到对应的关系了。相反第二个流程就很清楚了,调用resolve()就能跳转发到then()方法就能执行处理代码,then()回调的返回值又是一个promise对象。层次很明显,只要是then()必然是执行处理代码,如果还有嵌套必然就是返回了一个promise对象,这样调用就像Java中的StringBuffer的append()方法一样,链式调用。

javascript">new Promise((resolve, reject) => {
    setTimeout(() => {
    	resolve('success')
    }, 1000).then(success => {
    	console.log(success)
    })
})

setTimeout()模拟的是网络请求,而then()执行的是网络请求后的代码,这就将网络请求和请求得到的响应后的操作分离了,每个地方干自己的事情。在resolve中传参了,那么在then()方法中的参数就有这个参数,例如data。
网络请求中也会有失败情况?例如网络堵塞
如何处理失败情况,此时就要用到reject()

javascript">new Promise((resolve, reject) => {
    setTimeout(() => {
    	reject('error message')
    }, 1000).catch(error => {
    	console.log(error)
    })
})

此时reject(error)catch()方法捕获到reject()中的error。
合起来

javascript">new Promise((resolve, reject) => {
    setTimeout(() => {
        // 成功的时候调用resolve()
        // resolve('hello world')

        // 失败的时候调用reject()
        reject('error message')
    }, 1000).then(success => {
        console.log(success)
    }).catch(error => {
        console.log(error)
    })
})

拿ajax来举例子:

javascript">new Promise((resolve, reject) => {
    $.ajax({
        success:function(){
            // 成功的时候调用resolve()
            // resolve('hello world')

            // 失败的时候调用reject()
            reject('error message')
        }
    }).then(success => {
        console.log(success)
    }).catch(error => {
        console.log(error)
    })
})

3.Promise的三种状态

在这里插入图片描述

  • pending:等待状态,比如正在进行的网络请求还未响应,或者定时器还没有到时间
  • fulfill:满足状态,当我们主动回调了resolve函数,就处于满足状态,并会回调then()
  • reject:拒绝状态,当我们主动回调reject函数,就处于该状态,并且会回调catch()

4.Promies的链式调用

  • 网络请求响应结果为 hello ,打印hello

  • 处理: hello world ,打印hello world

  • 处理: hello world,vuejs ,打印hello world,vuejs

javascript"> new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('hello')
      }, 1000)
    }).then(res => {
      console.log(res)//打印hello
      return new Promise(resolve => {
          resolve(res + ' world')
      }).then(res => {
        console.log(res)//打印hello world
        return new Promise(resolve => {
          resolve(res + ',vuejs')
        }).then(res => {
          console.log(res)//打印hello world,vuejs
        })
      })
    })

链式调用就是then()方法的返回值返回一个Promise对象继续调用then(),此外还有简写Promise.resolve()

javascript">new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('hello')
      }, 1000)
    }).then(res => {
      console.log(res)//打印hello
      return Promise.resolve(res + ' world')
    }).then(res => {
        console.log(res)//打印hello world
        return Promise.resolve(res + ',vuejs')
    }).then(res => {
      console.log(res)//打印hello world,vuejs
    })

还可以直接省略掉Promise.resolve()

javascript"> new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('hello')
      }, 1000)
    }).then(res => {
      console.log(res)//打印hello
      return res + ' world'
    }).then(res => {
        console.log(res)//打印hello world
        return res + ',vuejs'
    }).then(res => {
      console.log(res)//打印hello world,vuejs
    })

如果中途发生异常,可以通过catch()捕获异常

javascript"> new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('hello')
      }, 1000)
    }).then(res => {
      console.log(res)//打印hello
      return res + ' world'
    }).then(res => {
        console.log(res)
        // return Promise.reject('error message')//发生异常
        throw 'error message' //抛出异常
    }).then(res => {
      console.log(res)//打印hello world,vuejs
    }).catch(error => {
      console.log(error)
    })

也可以通过throw抛出异常,类似java

javascript">throw 'error message' //抛出异常

5.Promies的all使用

有这样一个情况,一个业务需要请求2个地方(A和B)的数据,只有A和B的数据都拿到才能走下一步。
ajax实现

javascript">$.ajax({
    ...//结果A
    resultA = true
    callback()
})
$.ajax({
    ...//结果B
    resultB = true
    callback()
})
//回调函数
function callback(){
    if(resultA&&resultB){
        ...
    }
}

由于不知道网络请求A和网络请求B哪个先返回结果,所以需要定义一个函数只有2个请求都返回数据才回调成功。

Promise实现

javascript"> Promise.all([
      new Promise((resolve, resjct) => {
        $.ajax({
          url: 'url1',
          success: function (data) {
            resolve(data)
          }
        })
      }),
      new Promise((resolve, resjct) => {
        $.ajax({
          url: 'url2',
          success: function (data) {
            resolve(data)
          }
        })
      }).then(results => {
        console.log(results)
      })
    ])

上面是伪代码,只是包装了ajax,ajaxA和ajaxB的结果都放在resolve()中,Promise将其放在results中了,使用setTimeout模拟。

javascript"> Promise.all([
      new Promise((resolve, reject) => {
        setTimeout(() => {//  请求A
          resolve('结果A')
        }, 1000)
      }),
      new Promise((resolve, reject) => {
        setTimeout(() => {//  请求B
          resolve('结果B')
        }, 1000)
      })
    ]).then(results => {
      console.log(results)
    })

http://www.niftyadmin.cn/n/1319713.html

相关文章

对于数据中心的一些体会

最近因为同事的调职与处长的出差,数据中心的事情,最终还是落在自己的手上。经过一两天的梳理,觉得可以近期需要搞懂以下几个事情。1.现阶段数据中心的需求方面的困难的本质原因是什么,依靠什么样的途径可以解决。2.数据中心的元数…

20-axios的封装

1. axios简介 1.1 什么是axios axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 1.2 特性 浏览器端发起XMLHttpRequests请求node端发起http请求支持Promise API监听请求和返回转化请求和返回取消请求自动转化json数据客户端支持抵御 2. ax…

js获取wondow.location.href相对路径

首先获取 Url,然后把 Url 通过 // 截成两部分,再从后一部分中截取相对路径。如果截取到的相对路径中有参数,则把参数去掉。function GetUrlRelativePath(){var url document.location.toString();var arrUrl url.split("//");var…

Linux 命令修改图片尺寸!

今天写新浪微博发现有好多照的照片要传但是都很大写个命令将图片批量处理成800600大小的!find ./ -name *JPG -exec convert -resize 800x600 {} {} \;转载于:https://www.cnblogs.com/storymedia/archive/2011/04/10/4436127.html

uniapp开发微信小程序注意事项

uniapp开发微信小程序开发注意事项 在template中不要使用复杂的逻辑代码,尤其是在v-for做判断时,尽量用方法替代在template中不要直接出现空字符串,空对象,使用变量去替代若拉取的代码一致,但有一方报错,可…

小程序跳转另外小程序

wx.navigateToMiniProgram({appId: xxxxxxxxxxxxxxxxxx, // 要跳转的小程序的appidpath: page/index/index, // 跳转的目标页面extarData: {open: auth},success(res) {// 打开成功 } }) 注意:从小程序A内跳转到小程序B内有一个前提条件:A和B必须被同一…

一个简单的MFC中TreeView使用

今天用MapX写图层管理是,使用TreeView来显示和管理图层,样式模仿ArcGIS的样式,可以通过勾选相应的图层来决定相应的图层是否显示,可是在CTreeCtrl使用上不熟悉,郁闷了好长时间,用从各种地方找了很多资料&am…

小程序-保存图片到相册拒绝授权后,重新调用授权保存图片到相册

1.开发工具上的代码(ok) wx.saveImageToPhotosAlbum({filePath: canvasImg,success: function (res) {wx.showToast({title: 保存成功,image: "../images/nologo.png",duration: 1500,})},fail: function (res) {console.log(res)if (res.err…