异步
(一)同步与异步的区别
- 同步:代码立刻执行,拿到结果才走。
- 举例说明:蒸好米饭再炒菜
- 异步:不能直接拿到结果,代码会继续向下执行
- 蒸米饭的时候就炒菜。 (二)JS中典型的异步例子
- setTimeout
- AJAX
- AddEventListener 如果一个函数的结果处于上述这类函数的函数体内,那么这个函数是异步函数。 举例说明:
function RDM(){
setTimeout(()=>{
return Math.random()
})
}
分析:
- RDM没有写return 所以return undefined
- 箭头函数里的return才是RDM真正的结果
- 我们无法拿到setTimeout里真正的结果,该怎么办呢?
回调
(一)定义
回调的实质是一个函数。
写给自己调用的函数,不是回调;
写给别人调用的函数,才是回调。
(二)举例:
应用回调的方法,拿到RDM函数中setTimeout里的结果
//f1就是回调函数,我并没有调用,而是给RDM调用
function fn(x){ console.log(x) }
function RDM(fn){
setTimeout(()=>{
fn( Math.random() )
})
}
RDM(fn)
回调函数的简化
上面的例子可以简化成这种写法:
function RDM(fn){
setTimeout(()=>{
fn( Math.random() )
})
}
//简化后的方式
//RDM(x=>{
// console.log(x)
// })
//更加简化的方式
RDM(console.log)
- 适用范围:回调函数接收的参数个数 和回调函数中调用的函数的参数个数相等。
(x,y)=> { console.log(x) }就无法使用上述的简化方式
小总结
- 异步任务无法立刻拿到结果
- 于是我们给异步任务传入一个回调函数
- 异步任务完成时会调用回调函数
- 调用回调函数时会把异步任务的结果,当作参数传入回调函数
Promise
(一)定义:
- Promise 是异步编程的一种解决方案
- 所谓
Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。 (二)基本应用
- return new Promise((resolve,reject)=>{})
- 任务成功调用resolve(value),失败调用reject(error).
(注:
resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。) resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果value,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”,在异步操作失败时调用,并将异步操作报出的错误error,作为参数传递出去。- 通过
.then((value)=>{},(error)=>{})使用成功函数和失败函数,对promise对象中传出的value,error值进行处理。 注意:resolve和reject传出的参数都是唯一的,多值传参需要使用对象或者数组的形式。 - 如果在
then中 使用了return,那么return的值会被Promise.resolve()包装(返回一个新的promise)后续可以继续使用.then()(三)应用实例
function timeout(ms) {
return new Promise((resolve, reject) => {
setTimeout(resolve('done'), ms);
});
}
timeout(100).then((value) => {
console.log(value);
});
//done
- 上面代码中,
timeout方法返回一个Promise实例。 - 过了指定的时间(
ms参数)以后,Promise实例的状态变为成功,resolve函数将参数'done'传递出去,触发then方法绑定的回调函数。 (四)其他API
-
Promise.all(
iterable)- 方法返回一个
Promise实例,此实例在 迭代器**iterable**内所有的promise都“resolved”或参数中不包含promise时回调完成(resolve); - 如果参数中
promise有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败promise的结果。
const promise1 = Promise.resolve(3); const promise2 = 42; const promise3 = new Promise((resolve, reject) => { setTimeout(resolve, 100, 'foo'); }); Promise.all([promise1, promise2, promise3]) .then(values => console.log(values);); - 方法返回一个
-
Promise.race(
iterable)- 方法返回一个
promise,一旦迭代器**iterable**中的某个promise解决或拒绝,返回的promise就会解决或拒绝。
Promise.race([promise1,promise2]) .then(value=>console.log(value)); - 方法返回一个
-
Promise.catch(()=>{..})
- 在一个promise对象处于rejected后可以调用catch方法,接受reject传递的参数,并执行一个回调函数
-
Promise.allSettled
- 该方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
- 有多个彼此不依赖的异步任务成功完成时,或者想知道每个promise的结果时,通常使用allSettled。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.allSettled(promises).then((results) =>console.log(results));
// [Object { status: "fulfilled", value: 3 }, Object { status: "rejected", reason: "foo" }]