天天看点

javascript异步:callback-promise-async/await一、相关概念二、callback三、Promise四、Async\await参考

javascript异步:callback-promise-async/await

  • 一、相关概念
    • 1、异步和同步
    • 2、阻塞和非阻塞
  • 二、callback
  • 三、Promise
    • 1.Promise含义
    • 2.基本用法
    • 3、Promise异步(demo实例)
    • 3、Promise.all
  • 四、Async\await
    • 1、含义
    • 2、用法
      • 2.0、await\async
      • 2.1、await-resolve
      • 2.3、reject-then/catch
      • 2.4、reject-try/catch
  • 参考

JS三座大山:原型原型链、作用域闭包、同步异步。

一、相关概念

首先我们先了解同步、异步,阻塞、非阻塞等四个概念;

1、异步和同步

  • 同步和异步强调的是消息通信机制 (synchronous communication/ asynchronous communication)
  • 同步是指:当程序1调用程序2时,程序1停下不动,直到程序2完成回到程序1来,程序1才继续执行下去。
  • 异步是指:当程序1调用程序2时,程序1径自继续自己的下一个动作,不受程序2的的影响。

2、阻塞和非阻塞

  • 阻塞和非阻塞强调的是程序在等待调用结果(消息,返回值)时的状态.
  • 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
  • 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

二、callback

例子:

function foo(callback){//定义函数的时候将另一个函数(回调函数)作为参数传入定义的函数中。
    $ajax({
        //...
        success:callback//异步操作执行完毕后,再执行该回调函数,确保回调在异步操作之后执行。
    });
}
function myCallback(result){
    //...
}
foo(myCallback);
           

关于回调函数可以参考我的另外一篇博客:JavaScript同步回调和异步回调(个人理解)

三、Promise

1.Promise含义

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

2.基本用法

  • 例子
function f1(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      resolve('sucess')
    } else {
      reject('faile')
    }
  });
}
f1(1).then(function (result) {
  console.log(result)
})
//输出sucess
           
  • (1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
  • (2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

3、Promise异步(demo实例)

例子1

// 故意把f1函数写错(data写错成dat)
function f1(dat) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      resolve('sucess')
    } else {
      reject('faile')
    }
  });
}
function f2(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      resolve('sucess')
    } else {
      reject('faile')
    }
  });
}
f1(1).then(function (result) {
  console.log(result)
})
  .catch(function (error) { console.log(error) });

f2(2).then(function (result) {
  console.log(result)
})
  .catch(function (error) { console.log(error) });
           
  • 输出如下图,可以看到,即使f1出错了,f2也输出了函数的结果
javascript异步:callback-promise-async/await一、相关概念二、callback三、Promise四、Async\await参考

3、Promise.all

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

  • 只有Promise.all()中多个实例的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。
function f1(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      resolve('sucess-1')
    } else {
      reject('faile-1')
    }
  });
}
function f2(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      resolve('sucess-2')
    } else {
      reject('faile-2')
    }
  });
}
Promise.all([f1(1), f2(2)])
  .then(function (result) {
    console.log(result)
  })
  .catch(function (error) { 
    console.log(error) });
// faile-2
           

四、Async\await

Async\await和Promise一样是非阻塞的,Async 的价值在于用写同步的方式写异步,1避免了阻塞,2必免写回调

1、含义

ES2017 标准引入了 async 函数,使得异步操作变得更加方便。

async 函数是什么?一句话,它就是 Generator 函数的语法糖。(这是阮一峰说的,不是太明白,generate函数在此不展开,后期研究清楚后再讲)

  • async:定义异步函数

    1)自动把函数转换为Promise

    2)当调用异步函数时,函数返回值会被resolve处理

    3)异步函数内部可以使用await

  • await:暂停异步函数的执行

    1)当使用在Promise前面时,await等待Promise完成,并返回Promise的resolve的结果

    2)await只能和Promise一起使用,不能和callback一起使用

    3)await只能用在async函数中

2、用法

async 函数返回一个 Promise 对象,promise 返回的 resolve 对象可能用 await 去接,但是 reject 无法用 await 接收到,所以要用 try catch 去处理。(当然还有Promise运行过程中的错误,也可以catch到)

2.0、await\async

async:自动把函数转换为Promise;所以,此处的async function f1(), 和2.1中的**return new Promise()**是一样的;

async function f1(data) {
    if (data === 1) {
        console.log('sucess-1')
        return 'sucess-1'
    } else {
        console.log('faile-1')
        return 'faile-1'
    }
}

async function f3() {
    var f11 = await f1(1);
    console.log(f11 + 'main')
}
f3()
// sucess-1
// sucess-1main
           

2.1、await-resolve

以下demo正常运行;

  • 例子1
function f1(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      console.log('sucess-1')
      resolve('sucess-1')
    } else {
      console.log('faile-1')
      reject('faile-1')
    }
  });
}

async function f3() {
  var f11 = await f1(1);
  console.log(f11+'main')
}
f3()
// sucess-1
// sucess-1main
           

把上面例子输入改为2,可以看到f11并没有收到返回值;并且代码报错了

  • 例子2
function f1(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      console.log('sucess-1')
      resolve('sucess-1')
    } else {
      console.log('faile-1')
      reject('faile-1')
    }
  });
}

async function f3() {
  var f11 = await f1(2);
  console.log(f11+'main')
}
f3()
           

错误信息如下

javascript异步:callback-promise-async/await一、相关概念二、callback三、Promise四、Async\await参考

2.3、reject-then/catch

用catch接收Promise中的错误,await接收resolve,

  • 例子3(外层catch错误)

    then接收返回值,catch捕捉Promise中reject的错误,和运行中的错误;

function f1(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      console.log('sucess-1')
      resolve('sucess-1')
    } else {
      console.log('faile-1')
      reject('faile-1')
    }
  });
}

async function f3() {
  var f11 = await f1(2);
  console.log(f11 + 'main')
}
f3()
  .then(function (result) {
    console.log(result)
  })
  .catch(error => {
    console.log(error + 'catch')
  })
// faile-1
// faile-1catch
           

2.4、reject-try/catch

  • 例子4:

    直接在await的外层使用try/catch(即async里面catch错误)

function f1(data) {
  return new Promise(function (resolve, reject) {
    if (data === 1) {
      console.log('sucess-1')
      resolve('sucess-1')
    } else {
      console.log('faile-1')
      reject('faile-1')
    }
  });
}

async function f3() {
  try{
    var f11 = await f1(2);
  }catch(error){
    console.log(error+'try/catch')
  };
  console.log(f11 + 'main')
}
f3()
// faile-1
// faile-1try/catch
// undefinedmain

           

参考

【1】同步(Synchronous)和异步(Asynchronous)

【2】同步和异步的概念

【3】JS 异步(callback→Promise→async/await)

【4】阮一峰-Promise 对象

【5】阮一峰-async 函数的含义和用法

继续阅读