JavaScript异步编程笔记

一、JavaScript异步编程

1.同步模式

console.log('global begin')
function bar () {
  console.log('bar task')
}
function foo () {
  console.log('foo task')
  bar()
}
foo()
console.log('global end')
// 执行引擎会把所有的代码在调用栈(类似工作表)中压入一个匿名函数全局调用, 然后逐行执行,将第一行压入调用栈,控制台打印global begin,调用结束弹出调用栈 往后循环,

2.异步模式

console.log('global begin')

setTimeout(function timer1 () {
  console.log('timer1 invoke')
}, 1800)
setTimeout(function timer2 () {
  console.log('timer2 invoke')
  setTimeout(function inner () {
    console.log('inner invoke')
  }, 1000)
}, 1000)
console.log('global end')

以上调用顺序
1.将所有代码在调用栈中压入一个匿名函数全局调用,执行第一行,因为是同步代码,直接执行 打印出global begin
2.遇到setTimeout异步代码,将timer1 放入到API环境中等待执行,1.8s后
3.遇到setTimeout异步代码,将timer2 放入到API环境中等待执行 1s后
4.遇到console.log同步代码,直接执行 打印出 global end
5. timer2等待时间短,时间结束后timer2放入到消息队列(queue)中的第一位,然后timer1放入到消息队列
6.一旦调用栈执行完,事件循环(event loop)就会监听到然后将消息队列中的第一个任务压入调用栈执行,打印出timer2 invoke
然后再打印出timer1 invoke
7.在timer2中执行的时候,遇到异步代码,将inner放入到API环境中等待执行,timer1执行完后,inner进入消息队列,打印inner invoke

二、回调函数(异步编程函数的基础)

promise 三种状态,pending,Fulfilled(成功) ,Rejected (失败) 成功或失败一旦确定无法修改。

// Promise 基本示例

const promise = new Promise(function (resolve, reject) {
  // 这里用于“兑现”承诺
  // resolve(100) // 承诺达成
  reject(new Error('promise rejected')) // 承诺失败
})

promise.then(function (value) {
  // 即便没有异步操作,then 方法中传入的回调仍然会被放入队列,等待下一轮执行
  console.log('resolved', value)
}, function (error) {
  console.log('rejected', error)
})

console.log('end')

function ajax (url) {
  return new Promise(function (resolve, reject) {
    var xhr = new XMLHttpRequest()
    xhr.open('GET', url)
    xhr.responseType = 'json'
    xhr.onload = function () {
      if (this.status === 200) {
        resolve(this.response)
      } else {
        reject(new Error(this.statusText))
      }
    }
    xhr.send()
  })
}
ajax('/api/foo.json').then(function (res) {
  console.log(res)
}, function (error) {
  console.log(error)
})

Promise链式调用(then方法返回的也是一个链式调用,全新的promise对象,和原promise不等)
后面的then方法就是在为上一个then返回的promise注册回调
前面then方法中回调函数的返回值会作为后面then方法回调的参数
如果回调中返回的是Promise,那后面的then方法的回调会等待他的结束

ajax('/api/users.json')
  .then(function onFulfilled (value) {
    console.log('onFulfilled', value)
    return ajax('/error-url')
   }, function onRejected (error) { //这种写法是获取当前promise的异常
     console.log('onRejected', error)
   })
   
ajax('/api/users.json')
  .then(function onFulfilled (value) {
    console.log('onFulfilled', value)
    return ajax('/error-url')
  }) // => Promise {}
  // .catch(function onRejected (error) {  获取then方法返回的promise的异常
  //   console.log('onRejected', error)
  // })
Promise.resolve('foo')
  .then(function (value) {
    console.log(value)   // foo 
  })

new Promise(function (resolve, reject) {
  resolve('foo')
})

//如果传入的是一个 Promise 对象,Promise.resolve 方法原样返回

var promise = ajax('/api/users.json')
var promise2 = Promise.resolve(promise)
console.log(promise === promise2) //true

//如果传入的是带有一个跟 Promise 一样的 then 方法的对象,
Promise.resolve //会将这个对象作为 Promise 执行

//原生promise对象
Promise.resolve({
  then: function (onFulfilled, onRejected) {
    onFulfilled('foo')
  }
})
.then(function (value) {
  console.log(value)
})

//Promise.reject 传入任何值,都会作为这个 Promise 失败的理由
Promise.reject(new Error('rejected'))
  .catch(function (error) {
    console.log(error)
  })
Promise.reject('anything')
  .catch(function (error) {
    console.log(error)
  })

promise并行执行 promise.all 所有的promise执行完

var promise = Promise.all([
  ajax('/api/users.json'),
  ajax('/api/posts.json')
])

promise.then(function (values) {
  console.log(values)
}).catch(function (error) {
  console.log(error)
})

ajax('/api/urls.json')
  .then(value => {
    const urls = Object.values(value)
    const tasks = urls.map(url => ajax(url))
    return Promise.all(tasks)
  })
  .then(values => {
    console.log(values)
  })

promise.race 等待第一个promise结束

// Promise.race 实现超时控制

const request = ajax('/api/posts.json')
const timeout = new Promise((resolve, reject) => {
  setTimeout(() => reject(new Error('timeout')), 500)
})

Promise.race([
  request,
  timeout
])
.then(value => {
  console.log(value)
})
.catch(error => {
  console.log(error)
})

微任务(promise的回调作为微任务是任务执行完后再执行process.nextTick mutationObserver)


console.log('global start')
// setTimeout 的回调是 宏任务,进入回调队列排队
setTimeout(() => {
  console.log('setTimeout')
}, 0)
// Promise 的回调是 微任务,本轮调用末尾直接执行
Promise.resolve()
  .then(() => {
    console.log('promise')
  })
  .then(() => {
    console.log('promise 2')
  })
  .then(() => {
    console.log('promise 3')
  })

console.log('global end')

generator异步方案

function * foo () {
  console.log('start')

  try {
    const res = yield 'foo'
    console.log(res)
  } catch (e) {
    console.log(e)
  }
}

const generator = foo()

const result = generator.next()
console.log(result) //start
//{ value: 'foo', done: false }


// generator.next('bar')

generator.throw(new Error('Generator error'))  //Error: Generator error
function ajax (url) {
  return new Promise((resolve, reject) => {
    var xhr = new XMLHttpRequest()
    xhr.open('GET', url)
    xhr.responseType = 'json'
    xhr.onload = () => {
      if (xhr.status === 200) {
        resolve(xhr.response)
      } else {
        reject(new Error(xhr.statusText))
      }
    }
    xhr.send()
  })
}

function * main () {
  try {
    const users = yield ajax('/api/users.json')
    console.log(users)
    const posts = yield ajax('/api/posts.json')
    console.log(posts)
    const urls = yield ajax('/api/urls11.json')
    console.log(urls)
  } catch (e) {
    console.log(e)
  }
}
function co (generator) {
  const g = generator()
  function handleResult (result) {
    if (result.done) return // 生成器函数结束
    result.value.then(data => {
      handleResult(g.next(data))
    }, error => {
      g.throw(error)
    })
  }
  handleResult(g.next())
}
co(main)

async await

async function main () {
  try {
    const users = await ajax('/api/users.json')
    console.log(users)
    const posts = await ajax('/api/posts.json')
    console.log(posts)
    const urls = await ajax('/api/urls.json')
    console.log(urls)
  } catch (e) {
    console.log(e)
  }
}
// co(main)
const promise = main()

promise.then(() => {
  console.log('all completed')
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值