实用主义的异步与promise

423 阅读4分钟

异步

(一)同步与异步的区别

  1. 同步:代码立刻执行,拿到结果才走。
    • 举例说明:蒸好米饭再炒菜
  2. 异步:不能直接拿到结果,代码会继续向下执行
    • 蒸米饭的时候就炒菜。 (二)JS中典型的异步例子
  3. setTimeout
  4. AJAX
  5. 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) }就无法使用上述的简化方式

小总结

  1. 异步任务无法立刻拿到结果
  2. 于是我们给异步任务传入一个回调函数
  3. 异步任务完成时会调用回调函数
  4. 调用回调函数时会把异步任务的结果,当作参数传入回调函数

Promise

(一)定义:

  • Promise 是异步编程的一种解决方案
  • 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。 (二)基本应用
  1. return new Promise((resolve,reject)=>{})
  2. 任务成功调用resolve(value),失败调用reject(error). (注:resolvereject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。)
  3. resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”,在异步操作成功时调用,并将异步操作的结果value,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”,在异步操作失败时调用,并将异步操作报出的错误error,作为参数传递出去。
  4. 通过.then((value)=>{},(error)=>{})使用成功函数和失败函数,对promise对象中传出的value,error值进行处理。 注意:resolve和reject传出的参数都是唯一的,多值传参需要使用对象或者数组的形式。
  5. 如果在 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
  1. 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););
    
  2. Promise.race(iterable)

    • 方法返回一个 promise,一旦迭代器**iterable**中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
    Promise.race([promise1,promise2])
        .then(value=>console.log(value));
    
  3. Promise.catch(()=>{..})

    • 在一个promise对象处于rejected后可以调用catch方法,接受reject传递的参数,并执行一个回调函数
  4. 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" }]