当好几个异步方法同时发起请求时,响应的顺序是不能人为控制的。如果想要依次得到响应结果就必须嵌套。例如下程序,一定是先执行外层再执行内层。:
<script>
ajax("http://localhost:8000/tom","get",(res)=>{
console.log(res)
ajax("http://localhost:8000/jack","get",(res)=>{
console.log(res)
ajax("http://localhost:8000/jerry","get",(res)=>{
console.log(res)
})
})
</script>
多级异步函数的嵌套叫回调地狱。主要是代码不好看,代码嵌套太深
用promise解决回调地狱问题
Promise在new时,就自动执行异步任务。
node.js服务器代码:
var http = require('http')
http.createServer((req,res)=>{
res.writeHead(200,{
"Content-Type":"text/plain;charset=utf-8",
"Access-Control-Allow-Origin":"*"//解决跨域问题
})
if(req.url.endsWith('jack')){
setTimeout(function () {
res.write("jack响应成功")
res.end()
},3000)
}
if(req.url.endsWith('tom')){
setTimeout(function () {
res.write("tom响应成功")
res.end()
},3000)
}
if(req.url.endsWith('jerry')){
setTimeout(function () {
res.write("jerry响应成功")
res.end()
},1000)
}
}).listen(8000,()=>{
console.log("running...")
})
//ajax的简单封装:ajax.js
function ajax(url,type,callback) {
var xhr = new XMLHttpRequest()
xhr.onreadystatechange=function () {
if(xhr.readyState==4&&xhr.status==200){
callback(xhr.responseText)
}
}
xhr.open(type,url,true)
xhr.send(null)
}
用Promise解决回调地狱:
new Promise(function(open){
ajax("http://localhost:8000/tom","get",(res)=>{
console.log(res)
open()
})
})
.then(function(){
return new Promise(function(open){
ajax("http://localhost:8000/jack","get",(res)=>{
console.log(res)
open()
})
})
})
.then(function () {
ajax("http://localhost:8000/jerry","get",(res)=>{
console.log(res)
})
})
通过函数名。
function f1() {
return new Promise(res=>{
setTimeout( ()=> {
console.log("f11")
},1000)
res()
})
}
function f2() {
return new Promise(res=>{
setTimeout( ()=> {
console.log("f22")
},1000)
res()
})
}
function f3() {
return new Promise(res=>{
setTimeout( ()=> {
console.log("f33")
},1000)
})
}
f1().then(r=>{///此处r是上一步的函数执行完返回的参数。没有可以不写。
console.log(a)
return f2()
}).then(r=>{
return f3()
}).catch(r=>{
//catch是错误处理,如果成功回调里有错,这里也会处理。
console.log(r)
})
----
//以上方法不够简洁。
修改封装的ajax,将Promise封装进去。
function ajax(url,type,callback) {
return new Promise(function (open) {
var xhr = new XMLHttpRequest()
xhr.onreadystatechange=function () {
if(xhr.readyState==4&&xhr.status==200){
callback(xhr.responseText)
open()
}
}
xhr.open(type,url,true)
xhr.send(null)
})
}
然后,修改HTML代码。
ajax("http://localhost:8000/tom","get",(res)=>{
console.log(res)
})
.then(function(){
return ajax("http://localhost:8000/jack","get",(res)=>{
console.log(res)
})
})
.then(function(){
ajax("http://localhost:8000/jerry","get",(res)=>{
console.log(res)
})
})
Promise的错误处理
function ajax(url,type,callback) {
return new Promise(function (open,err) {
var xhr = new XMLHttpRequest()
xhr.onreadystatechange=function () {
if(xhr.readyState==4&&xhr.status==200){
if(Math.random()<0.7){//模拟出错。
callback(xhr.responseText)
open(’jjjjjj‘)//传递参数
}else{
console.log('有人出错')
}
}
}
xhr.open(type,url,true)
xhr.send(null)
})
}
html处:
<script src="ajax.js">
</script>
<script>
//第一步:先用Promise方法(带参数open)将每个异步方法包裹,最后一个除外。
//第二步:在每个Promise方法后追加.then方法。方法内将Promise return。
//第三部:在每个Promise内将open()调用。最后一个除外。
ajax("http://localhost:8000/tom","get",(res)=>{
console.log(res)
})
.then(function(data){
console.log(data)//接受参数
return ajax("http://localhost:8000/jack","get",(res)=>{
console.log(res)
})
})
.then(function(){
return ajax("http://localhost:8000/jerry","get",(res)=>{
console.log(res)
})
})
.catch(function (err) {//错误处理
console.log(err)
})
</script>
//以上是es6的写法。还不够简化。
es7的简化如下:
(async function(){//es7. async表示外部的大任务是异步的。
//await表示阻塞,里面的每个任务相当于是同步执行的。
try{
await ajax("http://localhost:8000/tom","get",(res)=>{
console.log(res)
})
await ajax("http://localhost:8000/jack","get",(res)=>{
console.log(res)
})
await ajax("http://localhost:8000/jerry","get",(res)=>{
console.log(res)
})
}catch (err) {
console.log(err)
}
})()