理解ES6中Promise,并用 Promise 封装一个 Ajax 请求(含express服务器创建和设置跨域)
1. 从基本理解开始
首先,Promise 是一个构造函数,可以用来 new 一个实例。
以前的异步编程当中,经常会出现地狱回调问题,也就是函数中嵌套很多层函数,而 Promise 就用于解决这个问题,使得代码看起来简洁很多。但是呢,它的代码看起来简洁,前提是要你懂得它的代码执行过程,你不懂它的执行过程,多简洁也白费,还不如层层嵌套的流程性看得容易明白一点。
下面用实例说明使用 Promise 实现异步编程中的代码执行过程。
1.1 先看看这个异步编程
setTimeout(()=>{ console.log('成功'); },1000) // 1s之后打印 成功 // 可是,这个过程一定会成功吗?也就是最终一定会打印出 成功 吗,不成功怎么办?
1.2 接着上面的例子,我们用 Promise 来看看
// 先 new 一个 Promise 实例 // new 实例的时候,传入一个函数 // 传进来的函数可以传进两个参数,名字可自定义,推荐分别为 resolve 和 reject // 两个参数中,第一个是异步操作中成功后回调的方法,第二个是失败后回调的方法,当然他们是可以省略的 let p = new Promise(function (resolve, reject) { setTimeout(() => { // 我们不像之前那样直接打印了,而是将“成功”或“失败”当参数传给这两个方法 // 成功就实行 resolve('成功!'),失败就执行 reject('失败!'),二选一 resolve('成功!') reject('失败!') }, 1000) }) // 执行完上面的代码后,其实什么也没打印出 // 接着到下面代码了,p 实例有个 then 的方法 // then 中又可以传进两个方法 // 第一个方法是上面执行了 resolve('成功!') 后执行的 // 第二个方法是上面执行了 reject('失败!') 后执行的 p.then( function (value) { // 形参 value,它传进来的实参是 '成功!' console.log(value) }, function (reason) { // 形参 reason,它传进来的实参是 '失败!' console.log(reason) } )
2. 用Promise封装Ajax请求
2.1 创建一个Express服务器,开启CROS跨域资源共享
// 1. 引入epress,记得先安装此模块 import epress from 'express' // 2. 执行epress(),用 app 接收 const app = epress() //3. 设置跨域访问(设置在所有的请求前面即可) app.all('*', function (req, res, next) { //3.1 设置允许跨域的域名,*代表允许任意域名跨域 res.header('Access-Control-Allow-Origin', '*') //3.2 允许的header类型 res.header('Access-Control-Allow-Headers', 'content-type') //3.3 跨域允许的请求方式 res.header('Access-Control-Allow-Methods', 'DELETE,PUT,POST,GET,OPTIONS') if (req.method == 'OPTIONS') res.sendStatus(200) //让options尝试请求快速结束 else next() }) // 5. 挂在路由 app.get('/user', (req, res) => { res.send({ data: { name: 'hong', sex: '男', age: 20 } }) }) // 4. 开启服务器 app.listen(80, () => { console.log('server runing at http://127.0.0.1') })
2.2 发起Ajax请求
(1)先使用常规的方式
执行过程说明:
- 请求成功了,执行打印 xhr.response 这个返回结果。
- 请求失败了,执行打印 请求失败!+ xhr.status
- 这样有 if else 嵌套问题
// 1. new 实例 var xhr = new XMLHttpRequest() // 2. 初始化 xhr.open('get', 'http://127.0.0.1/user') // 3. 发送 xhr.send() // 4. 绑定事件,处理结果 xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { // 4.1 处理请求成功后服务器返回是数据,这里只做简单的打印处理吧 console.log(xhr.response) } else { // 4.2 处理请求失败的情况 console.error('请求失败!' + xhr.status) } } } /* 4. 步骤4的另外一种实现方式 进入onload之后,只出现了状态码4。 也就是说,只有处于状态码4,请求已完成,响应已就绪的情况下,才会进入onload。 只要进入onload请求中,一定是已经到4这个状态了。 xhr.onload = function () { if (xhr.status === 200) { // 4.1 处理请求成功后服务器返回是数据,这里只做简单的打印处理吧 console.log(xhr.response) } else { // 4.2 处理请求失败的情况 console.error('请求失败' + xhr.status) } } */
(2)再使用Promise封装Ajax的方式
// 1. 创建 Promise 实例 let p = new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest() xhr.open('get', 'http://127.0.0.1/user') xhr.send() xhr.onload = function () { // 请求成功,执行resolve,并将返回的数据作为参数传入 resolve(xhr.response) // 请求失败 reject('请求失败' + xhr.status) } }) // 2. 处理成功和失败的回调 p.then( // 成功,res 得到的就是返回的数据 function (res) { console.log(res) }, // 失败,reason 得到的就是失败的返回原因 function (resaon) { console.log(reason) } )
3. 总结
Promise 实现异步编程过程中,代码整洁了,不用层层嵌套,也就是解决了地狱回调问题。
本文来自博客园,作者:RHCHIK,转载请注明原文链接:https://www.cnblogs.com/suihung/p/16249731.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)