promise基础
<script>
// Promise构造函数
var q = new Promise(function (resolve, reject) {
//异步
setTimeout(function () {
// 成功
// resolve(["111", "222", "333"]);
// 失败
reject("error");
}, 2000);
});
// q是promise对象
q.then(function (res) {
//兑现承诺,执行
console.log("success", res);
}).catch(function (err) {
// 拒绝承诺,执行
console.log("fail", err);
});
</script>
Promise实际是充当ajax获取后台数据后执行回调的异步执行顺序的一个媒介,客观来说就是避免ajax回调地狱(反复嵌套回调),不然代码不够直观。
Promise 流程总结:
1 .把 ajax 返回成功 / 失败的回调封装成一个 Promise 对象(同时判断 resolve / reject 状态)
2 .其对象根据传来的状态 resolve 则执行.then( res => {} // 实际在Promise.prototype上 )来执行ajax一层返回成功后的二层 ajax 请求,状态为 reject 的则执行对象的.catch( err => {} // 实际在Promise.prototype上 ),以此类推,实现异步请求的顺序执行
一个 Promise 必然处于以下几种状态之一:
待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
已兑现(fulfilled): 意味着操作成功完成。
已拒绝(rejected): 意味着操作失败。
一个Promise对象具有then函数,then函数接受两个函数,第一个函数当 Promise 变成接受状态(fulfilled)时被调用,第二个函数当 Promise 变成拒绝状态(rejected)时被调用。
catch 接收一个函数,在Promise被reject的时候执行,除非该函数抛出错误或返回一个失败的Promise,否则返回的Promise一直是resolved。实质上catch(failureCallback) 是 then(null, failureCallback) 的缩略形式。
finally接收一个回调函数,在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定该回调函数。这避免了同样的语句需要在then()和catch()中各写一次的情况。
使用promise封装Ajax解决回调地狱问题
//promise ajax
function pajax(options) {
return new Promise((resolve, reject) => {
ajax({
//展开运算符
...options,
success(res) {
resolve(res);
},
error(err) {
reject(err);
},
});
});
}
export { ajax, pajax };
<script>
pajax({
url: "http://localhost:3000/news",
data: { author: "王维" },
}).then((res) => {
console.log(res[0]);
return pajax({
url: "http://localhost:3000/comments",
data: { newsId: res[0].id },
})
.then((res) => {
console.log("success", res);
})
.catch((err) => {
console.log("error", err);
});
});
</script>
fetch基础内容:
Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应。它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源。
这种功能以前是使用 XMLHttpRequest 实现的。Fetch 提供了一个更理想的替代方案,可以很容易地被其他技术使用,例如 Service Workers。Fetch 还提供了专门的逻辑空间来定义其他与 HTTP 相关的概念,例如 CORS 和 HTTP 的扩展。
fetch 规范与 jQuery.ajax() 主要有以下的不同:
当接收到一个代表错误的 HTTP 状态码时,从 fetch() 返回的 Promise 不会被标记为 reject,即使响应的 HTTP 状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve(如果响应的 HTTP 状态码不在 200 - 299 的范围内,则设置 resolve 返回值的 ok 属性为 false),仅当网络故障时或请求被阻止时,才会标记为 reject。
fetch 不会发送跨域 cookie,除非你使用了 credentials 的初始化选项。
封装的Ajax方法和fetch比较:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>封装请求方式</title>
</head>
<body>
<button id="myget">GET</button>
<button id="mypost">POST</button>
<button id="myput">PUT</button>
<button id="mypatch">PATCH</button>
<button id="mydelete">DELETE</button>
</body>
<script>
// 查找
myget.onclick = function () {
// ajax({
// url: "http://localhost:3000/users",
// data: {
// username: "her",
// password: "345",
// },
// success: function (res) {
// console.log("success", res);
// },
// error: function (err) {
// console.log("error", err);
// },
// });
// fetch默认是get方法
// 查询操作:
var username = "her";
fetch(`http://localhost:3000/users?username=${username}`)
// fetch("http://localhost:3000/users")
.then((res) => {
console.log(res);
if (res.ok === true) {
//把数据当做json格式读取出来
return res.json();
} else {
//拒绝承诺
return Promise.reject({
status: res.status,
statusText: res.statusText,
});
}
//返回一个字符串,文本格式
// return res.text();
})
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log("error", err);
});
// fetch不支持catch方法,所以自己要写一个if语句去判断是否连接成功
};
// 插入
mypost.onclick = function () {
// ajax({
// url: "http://localhost:3000/users",
// method: "POST",
// data: { name: "test", value: "77" },
// headers: {
// "content-type": "application/json",
// },
// success: function (res) {
// console.log("success", res);
// },
// error: function (err) {
// console.log("error", err);
// },
// });
//使用post方法,需要传参数
fetch("http://localhost:3000/users", {
method: "POST",
headers: {
"content-type": "application/json",
},
//这里对象格式要转换成JSON格式才能进行前后端交互
body: JSON.stringify({ username: "heFan", age: "22" }),
})
.then((res) => res.json())
.then((res) => {
console.log(res);
});
};
//修改:put:全部覆盖
myput.onclick = function () {
// ajax({
// url: "http://localhost:3000/users/4",
// method: "PUT",
// data: { name: "window", password: "11123" },
// headers: {
// "content-type": "application/x-www-form-urlencoded",
// },
// success: function (res) {
// console.log("success", res);
// },
// error: function (err) {
// console.log("error", err);
// },
// });
fetch("http://localhost:3000/users/3", {
method: "PUT",
headers: {
"content-type": "application/json",
},
//这里对象格式要转换成JSON格式才能进行前后端交互
body: JSON.stringify({ username: "heFan", age: "22" }),
})
.then((res) => res.json())
.then((res) => {
console.log(res);
});
};
//patch:部分覆盖(修改)
mypatch.onclick = function () {
// ajax({
// url: "http://localhost:3000/users/4",
// method: "PATCH",
// data: { name: "feifei", sex: "woman" },
// headers: {
// "content-type": "application/x-www-form-urlencoded",
// },
// success: function (res) {
// console.log("success", res);
// },
// error: function (err) {
// console.log("error", err);
// },
// });
fetch("http://localhost:3000/users/4", {
method: "PATCH",
headers: {
"content-type": "application/json",
},
//这里对象格式要转换成JSON格式才能进行前后端交互
body: JSON.stringify({ username: "heFan", age: "22" }),
})
.then((res) => res.json())
.then((res) => {
console.log(res);
});
};
//delete:删除
mydelete.onclick = function () {
// ajax({
// url: "http://localhost:3000/users/4",
// method: "DELETE",
// headers: {
// "content-type": "application/x-www-form-urlencoded",
// },
// success: function (res) {
// console.log("success", res);
// },
// error: function (err) {
// console.log("error", err);
// },
// });
fetch("http://localhost:3000/users/1", {
method: "DELETE",
headers: {
"content-type": "application/json",
},
//这里对象格式要转换成JSON格式才能进行前后端交互
body: JSON.stringify({ username: "heFan", age: "22" }),
})
.then((res) => res.json())
.then((res) => {
console.log(res);
});
};
</script>
</html>
console.log(res);
输出结果:
因为fetch函数,不会判断错误,走catch那条路,就算URL写错,也会执行成功的then:
.then((res) => {
console.log("success", res);
})
.catch((err) => {
console.log("error", err);
});
结果:success undefined
所以,要自己写一个判断条件,来确认是否连接成功:
if (res.ok === true) {
//把数据当做json格式读取出来
return res.json();
} else {
//拒绝承诺
return Promise.reject({
status: res.status,
statusText: res.statusText,
});
}
至于post、put、delete方法,需要写参数,以及决定数据格式:
{
method: "POST",
headers: {
"content-type": "application/json",
},
//这里对象格式要转换成JSON格式才能进行前后端交互
body: JSON.stringify({ username: "heFan", age: "22" }
详细内容可阅读开发文档:使用 Fetch