- Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
- Promise 是一个 ECMAScript 6 提供的类,目的是更加优雅地书写复杂的异步任务。
- Promise是一个构造函数,通过new来实例化,主要解决异步编程。
- 在 ES2015 中,Promise 诞生了。Promise 成功解决了回调函数中嵌套调用和错误跟踪、回调函数控制权等问题。
- 一个Promise对象有三种状态:pending(等待中)、fulfilled(已成功)或rejected(已失败)。当Promise对象处于pending状态时,它表示尚未完成,但可能会在未来某个时间完成。
简单回调:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
console.log("发送第一个请求")
setTimeout(function (){
console.log("第一个请求结束")
console.log("同时发送第二个请求")
setTimeout(function (){
console.log("第二个请求结束")
console.log("发送第三个请求")
setTimeout(function (){
console.log("第三个请求结束")
}, 1500)
}, 1000)
}, 500)
</script>
</head>
<body>
</body>
</html>
promise基本使用
new Promise(function(resolve, reject) { });
例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function f1(){
var p = new Promise(function (resolve, reject){
console.log("发送了ajax请求1")
setTimeout(function (){
//模拟返回包
let response_data = "你好,欢迎光临xxx网站"
let code = 500
if(code === 500){
// resolve执行将 promise的状态调整为 fulfilled
resolve(response_data)
}else{
// reject执行将 promise的状态调整为 rejected
reject("111111")
}
}, 5000)
})
return p
}
// 等待状态
let p = f1()
p.then(function (res){
// then的第一个函数触发条件: promise的状态调整为 fulfilled
console.log("返回数据:", res)
console.log("响应结束")
}, function (){
// then的第二个函数触发条件: promise的状态调整为 rejected
})
</script>
</head>
<body>
</body>
</html>
then函数
Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数**。** Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。 then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
如果初始函数里面没有指定resolve或者reject函数,那么 .then 函数是不会被调用的,因为之后状态变成了resolved或者rejected才会调用对应的回调函数。
链式应用
使用Promise可以更好地处理异步操作,例如网络请求,文件读取等。它避免了死亡回调(callback hell)的问题,使得代码更加容易理解和维护。
笨的例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function f1(){
return new Promise(function (resolve, reject){
console.log("发送第一个请求")
setTimeout(function (){
resolve("第一个返回值!")
}, 1000)
})
}
let p = f1()
p.then(function (res){
// 第一个请求处理
console.log("返回:::", res)
var p = new Promise(function (resolve, reject){
console.log("发送第二个请求")
setTimeout(function (){
resolve("第二个返回值!")
}, 2000)
})
p.then(function (res){
console.log("第二个的返回:::", res)
})
})
</script>
</head>
<body>
</body>
</html>
这样并不能达到简洁的目的。
改进:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function f1(){
return new Promise(function (resolve, reject){
console.log("发送第一个请求")
setTimeout(function (){
resolve("第一个返回值!")
}, 1000)
})
}
function f2(){
return new Promise(function (resolve, reject){
console.log("发送第二个请求")
setTimeout(function (){
resolve("第二个返回值!")
}, 2000)
})
}
function f3(){
return new Promise(function (resolve, reject){
console.log("发送第三个请求")
setTimeout(function (){
console.log("第三个返回值!")
}, 3000)
})
}
let p = f1()
p.then(function (res){
// 第一个请求处理
console.log("第一个返回:::", res)
return f2()
}).then(function (res){
console.log("第二个返回:::", res)
return f3()
}).then(function (res){
console.log("第三个返回:::", res)
})
</script>
</head>
<body>
</body>
</html>
也就是链式调用
简单应用:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.js"></script>
</head>
<body>
<script>
function GetData(url){
return new Promise(function (resolve, reject){
console.log("开始发送")
$.ajax({
url: url,
success: function (res){
resolve(res)
}
})
});
}
let base_url = "https://devapi.qweather.com/v7/weather/now?location=101070101&key=0718ad154da14f0a98ca49778f9bfd53"
GetData(base_url).then(function (res){
console.log("response_data:::", res.now)
return GetData(base_url)
}).then(function (res){
console.log("response_data:::", res.refer)
})
</script>
</body>
</html>