promise :什么是promise呢?
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。这是官方给出的答案。
简单理解 Promise是解决回调地狱的方案之一 把回调地狱写的优雅的方案之一
简单举个例子:
Promise 单词
+ 承诺, i promise, i will love you forever
+ 这个承诺有几个状态(三个)
1. 承诺继续 => 两个人在一起过日子
2. 成功 => 最后两个人埋在一个坟里面
3. 失败 => 有一个人埋在别人的坟里
+ 一旦状态确定, 不可变更
=> 继续 -> 成功
=> 继续 -> 失败
=> 不可能由成功转变为失败
+ 对应在 Promise 的语法里面的时候
=> 继续 -> pending -> 正在进行时
=> 成功 -> fulfilled -> 过去完成时
=> 失败 -> rejected -> 过去完成时
(1)
Promise 是做什么的
+ 承诺会帮你做 异步的事情
+ 会在成功的时候给你一个成功的回调
+ 会在失败的时候给你一个失败的回调
+ 我们把异步的事情交给 promise 来做
=> 我们等待结果就好
=> pending 继续, 也就是正在帮你做这个异步的事情
=> fulfilled 成功, 结果
=> rejected 失败, 结果
(2)
Promise 类比在 ajax 请求里面
=> pending 就是正在请求(网络传输过程中)
=> fulfilled 就是请求成功了(网络环境允许请求, 可以连接到服务器拿到结果)
=> rejected 就是请求失败了(突然没有网了, 掉线了, 不会再有结果回来了)
(3)
Promise 的语法
+ 在 es6 里面有一个内置的构造函数叫做 Promise
+ 语法: let p1 = new Promise(function () { 你要做的异步的事情 })
+ promise 对象里面由两个方法
+ 一个叫做 then => 就是 p1 帮你做的异步的事情成功的时候执行的
+ 一个叫做 catch => 就是 p1 帮你做的异步的事情失败的时候执行的
举个例子:
// 应用一下 promise
// 先用定时器来模拟
var p1 = new Promise(function (resolve, reject) {
// 帮我做一件异步的事情
var xhr = new XMLHttpRequest()
xhr.open('请求方法', 'URL路径')
xhr.onreadystatechange = function () {
if (xhr.status === 200 && xhr.readyState === 4) {
resolve(xhr.responseText) // 实参
// 给的就是后端返回的内容
}
if (xhr.status === 404) {
reject('请求地址不对')
}
}
xhr.send()
})
// then 函数
p1.then(function (res) { // 形参
console.log('我执行了, 我表示成功')
// res 接受到的就是 resolve () 里面的实参 => 100
// res 接收到的就是 后端返回的内容
console.log(res)
})
// catch 函数
p1.catch(function () {
console.log('我执行了, 我表示失败')
})
- 现在上面这段代码的执行顺序
1. 遇到了一个 Promise帮我发送一个 ajax 请求
-> 发现这个是一个异步的 ajax
-> 就把这个 异步的 ajax 往后放
2. 遇到了一个 p1.then(function a() {})
-> 就把这个回调函数帮我们准备好了传递到 promise 里面
3. 遇到了一个 p1.catch(function b() {})
-> 就把这个回调函数帮我们准备好了传递到 promise 里面
到这个时候
-> 所有的同步代码都执行完毕了
-> a 和 b 函数只是传递到了 promise 里面, 但是没有调用
-> 接下来就该异步的 ajax 执行了
4. 等到 ajax 结束的时候
-> 根据 ajax 的状态或者说成功还是失败
-> 来调用之前就准备好的成功的回调或者失败的回调
Promise的链式调用
- Promise 的链式调用
+ then 是成功的回调
+ 只要 then 里面再次 return 一个 promise 对象
+ 那么就可以在这个 then 后面继续 then
举个例子
var p1 = new Promise(function (resolve, reject) {
// 异步的事情先用定时器模拟
setTimeout(function () {
resolve() // 成功的回调
}, 1000)
})
// 1s 以后执行这个 then 函数
p1.then(function () {
console.log('我是 p1 的 then 函数里面的代码')
// 准备第二个 promise 对象
var p2 = new Promise(function (resolve, reject) {
setTimeout(function () {
resolve() // 调用的第二个 then
}, 1000)
})
// p2 是一个 promise 对象
// 返回一个 promise 对象
return p2
}).then(function () {
// 我会在 p2 的 resolve() 的时候执行
console.log('我是 p1 then 后面的第二个 then')
})
// 在 p1 的 then 里面 return 了一个新的 promise 对象
优雅编程
-
优雅的编程
+ 使用 Promise 的方式二次封装 ajax需求:
1. 发送一个请求到 a.php
-> 能得到一个结果
-> 是两个数组
2. 发送第二个请求到 b.php, 需要在第一个请求结束以后发送
-> 需要携带第一个请求给返回来的两个数字
-> 能得到一个结果
-> 包含你带过去的两个数字的和, 和第三个数字
3. 发送第三个请求到 c.php, 需要在第二个请求结束以后发送
-> 需要携带第二个请求给返回来的两个数字
-> 能得到一个结果, 是两个数字的乘积
function pGetSend(url) {
// 利用 promise 帮我们做一个 异步的 ajax 请求
var p1 = new Promise(function (resolve, reject) {
// 直接发送一个 ajax 请求
var xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.onload = function () {
resolve(xhr.responseText) // 在请求成功的时候调用一下 resolve()
}
xhr.send()
})
return p1
}
pGetSend('./server/a.php')
.then(function (res) {
console.log('第一次请求的结果')
// 是个 json 格式, 我们不方便获取内容
// 使用 JSON.parse 解析一下
var result = JSON.parse(res)
console.log(result)
// return一个新的 promise 对象
return pGetSend(`./server/b.php?n1=${result.n1}&n2=${result.n2}`)
})
.then(function (res) {
console.log('第二次请求的结果')
// console.log(res) // json 格式, 我们要解析一下
var result = JSON.parse(res)
console.log(result)
return pGetSend(`./server/c.php?and=${result.and}&n3=${result.n3}`)
})
.then(function (res) {
console.log('第三次请求的结果')
console.log(res)
})
// a 得到的就是 pGetSend 这个函数里面 return 出来的东西
// pGetSend 里面 return 出来的就是 p1
// 等价于 a = p1
// var a = pGetSend('./server/a.php')
// // p1 之所以可以 .then 是因为 p1 是一个 promise 对象
// // 可以写 p1.then 就可以写 a.then
// a.then(function (res) {
// console.log(res) // 上面 p1 调用 resolve() 的时候传递的响应体
// })
其中php中代码
- a.php:
<?php
# 准备两个数组返回
$arr = array( "n1" => 100, "n2" => 200 );
// 变成 json 格式返回
echo json_encode($arr);
?>
- b.php
<?php
// 1. 接受前端传递来的参数
$n1 = $_GET['n1'];
$n2 = $_GET['n2'];
// 2. 求一个 和
$and = $n1 + $n2;
// 3. 准备一个关联型数组返回
$arr = array( "and" => $and, "n3" => 5 );
echo json_encode($arr);
?>
3.c.php:
<?php
// 1. 接受前端传递来的参数
$and = $_GET['and'];
$n3 = $_GET['n3'];
// 2. 求一个乘积
$chengji = $and * $n3;
// 直接返回数字
echo $chengji;
?>
async / await 语法
-
+es7 的语法
+ 把异步代码写的 看起来像 一个同步代码
-> 代码只是看着像是同步代码
-> 本质还是异步代码
+ 前提: Promise
+ async => 异步
+ await => 等待 -
语法规范
1. async 关键字必须写在一个函数的前面
2. await 关键字是一个写在 异步函数 里面的关键字
-> 你想使用 await 关键字, 那么函数前面必须有 async 关键字
3. await 关键字后面必须是一个 promise 对象
+ 有了 await 以后
+ 我们就可以把本该在 then 里面接受的结果
+ 在 await 前面定义一个变量来接受兼容性问题
+ 我们的 Promsie 和 async/await 语法都是兼容性不好
-> 一个是 es6 一个是 es7
-> 语法层面的兼容
+ 语法层面的兼容我们不需要考虑
-> 因为最后我们有一个工具叫做 babel
-> 能帮我们做的事情就是 es6 es7 转换成 es5 语法
+ 例子:
-> let num = 100, IE 低版本不兼容
-> let { name } = obj, IE 低版本不兼容
->hello ${a}, IE 低版本不兼容
-> 我们的 babel 就能把这种语法变成 es5 的语法
// pGetSend() 函数执行的时候能返回一个 promise 对象
function pGetSend(url) {
// 利用 promise 帮我们做一个 异步的 ajax 请求
var p1 = new Promise(function (resolve, reject) {
// 直接发送一个 ajax 请求
var xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.onload = function () {
resolve(xhr.responseText) // 在请求成功的时候调用一下 resolve()
}
xhr.send()
})
return p1
}
使用 async / await 语法完成刚才的三个需求
async function fn() {
// 1. 第一个请求
var res = await pGetSend('./server/a.php')
var result = JSON.parse(res)
console.log('第一次请求的结果')
console.log(result)
// 2. 第二个请求
var res2 = await pGetSend(`./server/b.php?n1=${result.n1}&n2=${result.n2}`)
var result2 = JSON.parse(res2)
console.log('第二次请求的结果')
console.log(result2)
// 3. 第三个请求
var res3 = await pGetSend(`./server/c.php?and=${result2.and}&n3=${result2.n3}`)
console.log('第三次请求的结果')
console.log(res3)
}
fn()
-
解释 async / await 语法
a 得到的就是一个 promise 对象
var a = pGetSend(’./server/a.php’)async function fn() {
这个本该在 then 里面接受的 res 就是后端的响应
如果你有 await, 就可以直接在 await 前面定义一个变量
来接受这个本该在 then 里面接受的内容
pGetSend(’./server/a.php’)
.then(function (res) {
console.log(res)
})res 接受的就是 pGetSend 的 then 里面接受的内容
var res = await pGetSend(’./server/a.php’)await 是什么意思
当 await 后面是一个 promise 对象的时候
那么就会把代码停止在这里不动了, 等到后面 promise 里面的异步事情做完以后
把结果给到前面的变量, 在继续向后执行代码
只生效在当前作用域内部, 也就是这个 async 函数内部
pGetSend 是一个异步的 ajax 请求
await 就会等到这个 异步的请求结束, 并且把结果给到前面的 res 变量以后
在继续向后执行 console.log(res) 这一句代码console.log(res)
}
调用一下上面的 fn 函数
fn()
Promise是JavaScript中用于解决异步编程问题的工具,它可以避免回调地狱,使代码更加优雅。Promise有三种状态:pending(进行中)、fulfilled(已完成)和rejected(已失败)。async/await是ES7引入的语法,使得异步代码看起来更像同步代码,通过await关键字可以等待Promise完成并获取结果。文章通过实例解释了如何使用Promise的链式调用和async/await进行优雅编程,并讨论了它们的兼容性问题。
1621

被折叠的 条评论
为什么被折叠?



