一、异步的定义
- 通过调用一个函数来启动一个长期运行的操作
- 让函数开始操作并立即返回,这样我们的程序就可以保持对其他事件做出反应的能力
- 当操作最终完成时,通知我们操作的结果。
二、Promise
1)定义:Promise 是现代 JavaScript 中异步编程的基础,是一个由异步函数返回的可以向我们指示当前操作所处的状态的对象。在
2)基本的链式使用,还有promise.all([]) 、promise.any([]) 等合并使用,都会返回一个promise 对象不同点是 all 是所有 promise 都执行成功后才会到 then 而 any 是其中一个执行成功就会到then。
const fetchPromise = fetch('bad-scheme://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json');
fetchPromise
.then( response => {
if (!response.ok) {
throw new Error(`HTTP 请求错误:${response.status}`);
}
return response.json();
})
.then( json => {
console.log(json[0].name);
})
.catch( error => {
console.error(`无法获取产品列表:${error}`);
});
3)状态:
-
待定(pending):初始状态,既没有被兑现,也没有被拒绝。这是调用
fetch()
返回 Promise 时的状态,此时请求还在进行中。 -
已兑现(fulfilled):意味着操作成功完成。当 Promise 完成时,它的
then()
处理函数被调用。 -
已拒绝(rejected):意味着操作失败。当一个 Promise 失败时,它的
catch()
处理函数被调用
4)自己实现promise
思路:维护 promise 的不同状态;维护promise的不同之行结果的回调函数;实现异步的监听;promise的链式使用的支持,想到了维护promise的回调函数队列;
// 状态常量
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';
class Promise {
constructor {
this.status = PENDING;
this.reason = undefined;
this.value = undefined;
this.onResolvedCallbacks = [];
this.onRejectedCallbacks = [];
}
let resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
// 依次将对应的函数执行
this.onResolvedCallbacks.forEach(fn=>fn());
}
}
let reject = (error) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = error.reason;
// 依次将对应的函数执行
this.onRejectedCallbacks.forEach(fn=>fn());
}
}
try {
executor(resolve,reject)
} catch (error) {
reject(error)
}
then(onFulfilled, onRejected) {
if (this.status === FULFILLED) {
onFulfilled(this.value)
}
if (this.status === REJECTED) {
onRejected(this.reason)
}
if (this.status === PENDING) {
// 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
});
// 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行
this.onRejectedCallbacks.push(()=> {
onRejected(this.reason);
})
}
}
}
三、generator 与 async 和 await
generator是ES6引入的进一步改善异步编程的方案, 将异步函数使用类似同步函数的的方式来编程,减少了代码中的嵌套,也提高了代码的可读性; async/await
其实是Generator和自动执行器的语法糖,写法和实现原理都类似co模块的promise模式
// gen是一个生成器函数
function* gen() {
let a = yield 1;
let b = yield a + 2;
yield b + 3;
}
let itor = gen(); // 生成器函数运行后会返回一个迭代器对象,即itor。
四、拓展
Web 中的异步API:setTimeOut() XMLHttpRequest
setTimeOut() XMLHttpRequest 的异步回调,是通过将回调函数封装成新的宏任务,添加到消息队列后面,当循环消息加载到该任务的时候执行回调函数。