回调
回调简介
回调是一种异步编程风格,将函数作为变量传入函数中,当触发某个条件时,调用该函数。
这是一个动态加载 js 脚本的函数。
function loadScript(src, callback) {
let script = document.createElement("script");
script.src = src;
script.onload = callback(null, script);
script.onerror = callback(new Error(`Script load error for ${src}`));
document.head.append(script);
}
使用该函数加载脚本。
loadScript("/myscript.js", function (error, script) {
if (error) {
// fail
} else {
// success
}
});
回调可以嵌套,即在回调要执行的动作中传入回调函数本身。但这种方式不建议使用,嵌套过多很容易损害代码可读性。
Promise 对象
异步操作一般是因为某些函数从执行操作,到产生结果中间有时间差,为了提高效率我们一般会阻塞这部分代码知道接受到返回结果,再执行相应的逻辑。
- 生产者:我们可以理解为异步的源头;
- 消费者:接受生产者返回结果的代码;
而 JavaScript 内置的 Promise 对象,就是用于连接生产者代码和消费者代码的对象。
构造语法如下:
let promise = new Promise(function (resolve, reject) {
let success = true;
// executor (生产者代码)
if (success) {
resolve("done");
} else {
reject(new Error("Error"));
}
});
Promise 对象有两个内置变量 state 和 result ,外部无法访问,只能通过 resolve 和 reject 两个函数改变,并且这种改变都是最终的。
- 初始态
{state: "pending", result: undefined}- 调用
resolve(value)后{state: "fulfilled", result: value} - 调用
reject(error)后{state: "rejected", result: error}
- 调用
消费者处理结果
消费者通过 then 和 catch 捕获 Promise 相应的状态,并执行相应的逻辑:
then()
then(f, f) 通过箭头函数向 promise.then() 传入两个函数,如果 resolve 了执行第一个,如果 reject 执行第二个。
promise.then(
result => alert(result), // alert("done");
error => alert(error) // alert("Error");
);
相当于对消费者 resolve 做出 promise 如果 promise 被生产者 resolve 了,便执行 promise.then() 的第一个函数,如果 reject 便执行第二个。
另外,如果我们只关心是否 resolve 或是否 reject ,代码如下:
catch()
catch(f) 可以捕获 reject 的 Error 对象,执行相应的回调。(其实不是 Error 对象也可以,reject 和 resolve 一样对参数类型无要求,后面再说)
// 只看是否 resolve
promise.then(alert);
// 只看是否 reject
promise.catch(alert);
finally()
// 无论什么结果都执行的,一般用来执行清理的操作。
promise.finally(() => exit());
finally(f)的回调f是没有参数的,它并不关心 promise 是否成功,只知道 promise 已经执行完了。finally(f)会将 promise 的结果传递到下面的处理程序中去,即可以被finally后面的then()和catch()捕获并处理。
promise.finally(() => alert("Promise ready"));
promise.then(
result => alert(result),
err => alert(err)
);