回调函数、Promise、Generator 函数和async函数
回调函数
<script>
function getFile(url, myCallback) {
let req = new XMLHttpRequest();
req.open("GET", url);
req.onload = function () {
if (req.status == 200) {
myCallback(req.responseText);
} else {
myCallback("Error: " + req.status);
}
};
req.send();
}
//错误url 404
getFile("../for-test.html", (res) => {
console.log(res); //Error: 404
});
//正确url
getFile("../../for-test.html", (res) => {
console.log(res); //test
});
</script>
多重请求导致的 回调地狱
<script>
function getFile(url, myCallback) {
let req = new XMLHttpRequest();
req.open("GET", url);
req.onload = function () {
if (req.status == 200) {
myCallback(req.responseText);
} else {
myCallback("Error: " + req.status);
}
};
req.send();
}
//多重请求时出现的多重回调函数嵌套('回调地狱')
getFile("../../for-test.html", (res) => {
console.log(res); //test
getFile("../for-test.html", (res) => {
console.log(res); //Error: 404
});
});
</script>
Promise
Promise 为了解决多重请求时出现的多重回调函数嵌套('回调地狱')。
<script>
function getFilePromise(url) {
let myPromise = new Promise((myResolve, myReject) => {
let req = new XMLHttpRequest();
req.open("GET", url);
req.onload = function () {
if (req.status == 200) {
myResolve(req.response);
} else {
myReject("Error: " + req.status);
}
};
req.send();
});
return myPromise;
}
getFilePromise("../../for-test.html")
.then((value) => {
console.log(value);
})
.then(() => {
return getFilePromise("../for-test.html");
})
.then((value) => {
console.log(value);
})
.catch(function (error) {
console.log(error);
});
</script>
Generator 函数
"协程"(coroutine),意思是多个线程互相协作,完成异步任务。协程 A 开始执行,协程 A 执行遇到异步任务,进入暂停,执行权转移到协程 B,协程 B 完成异步任务交还执行权给协程 A,协程 A 恢复执行。
Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。使用 function* funcname 和 yield 定义。调用 Generator 函数,会返回一个内部指针(即遍历器 )g,调用指针 g 的 next 方法,会移动内部指针,next 方法的作用是分阶段执行 Generator 函数。每次调用 next 方法,会返回一个对象,表示当前阶段的信息( value 属性和 done 属性)。value 属性是 yield 语句后面表达式的值,表示当前阶段的值;done 属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。
<script>
function* getFileGen(url) {
try {
let result = yield fetch(url);
} catch (error) {
//捕获函数体外抛出的错误
console.log(error);
}
return result;
}
var g = getFileGen("../../for-test.html");
var result = g.next();
console.log(result); //{value: Promise, done: false}
result.value
.then(function (data) {
return data.text();
})
.then(function (data) {
console.log(data); //test
console.log(g.next()); //{value: undefined, done: true}
});
//抛出错误
g.throw("出错了");
//产生的问题:流程管理(即何时执行g.next())
</script>
async 函数
async 函数,也就是我们常说的 async/await,是在 ES2017(ES8) 引入的新特性,主要目的是为了简化使用基于 Promise 的 API 时所需的语法。async 表示函数里有异步操作,await 表示紧跟在后面的表达式需要等待结果。await关键字只在 async 函数内有效,如果在 async 函数体之外使用它,会抛出语法错误。async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。await关键字可以跟在任意变量或者表达式之前,但通常await后面会跟一个异步过程。await使用时,会阻塞后续代码执行。
<script>
async function test() {
return "hello";
}
test()
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
async function test1() {
return new Promise(function (resolve, reject) {
if (true) {
resolve("hello");
} else {
reject("error");
}
});
}
test1()
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
async function test2() {
var result = await fetch("../../for-test.html")
.then((response) => response.text())
.catch((err) => console.log("Request Failed", err));
var result1 = await "test2";
console.log(result);
console.log(result1);
}
test2();
</script>
浙公网安备 33010602011771号