一、同步模式与异步模式
同步模式:
代码执行顺序与编写顺序一致,一旦某行代码过长,就会延迟后面的任务
异步模式:
不会等待这个任务的结束再去下一个任务,一般通过回调函数的方式定义后续逻辑,代码执行顺序相对较跳跃
回调函数是所有异步编程方案的根基
二、事件循环与消息队列
三、promise
const promise = new Promise(function (resolve, reject) {
// resolve(100) // 承诺达成
reject(new Error('promise rejected')) // 承诺失败
})
promise.then(function (value) {
console.log('resolved', value)
}, function (error) {
console.log('rejected', error)
})
console.log('end') // 先打印出end,再打印Error
-----------------------
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 100);
})
const p2 = Promise.resolve(2)
const p3 = Promise.reject(3)
p1.then(value => {console.log(value)})
p2.then(value => {console.log(value)})
p3.catch(reason => {console.log(reason)})
all [promises] 全部完成
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
race [promises] 一个完成
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
});
finally()
方法返回一个Promise
。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise
是否成功完成后都需要执行的代码提供了一种方式。
p.finally(function() {
// 返回状态为(resolved 或 rejected)
});
then链式调用
- 每一个then方法实际上,都是在为上一个then返回的promise对象添加状态明确过后的回调
- promise对象的then方法会返回一个新的promise对象
- 上一个then方法中回调的返回值会作为下一个then方法回调的参数
- 若回调中返回的是promise,下一个then的回调会等待它的结束
```javascript
function ajax (url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest()
xhr.open(‘GET’, url)
xhr.responseType = ‘json’
xhr.onload = function () {
} xhr.send() }) }if (this.status === 200) {
resolve(this.response)
} else {
reject(new Error(this.statusText))
}
ajax(‘/api/users.json’) .then(function (value) { console.log(1111) return ajax(‘/api/urls.json’) }) // => Promise .then(function (value) { console.log(2222) console.log(value) return ajax(‘/api/urls.json’) }) // => Promise .then(function (value) { console.log(3333) return ajax(‘/api/urls.json’) }) // => Promise .then(function (value) { console.log(4444) return ‘foo’ }) // => Promise .then(function (value) { console.log(5555) console.log(value) })
<a name="ura5t"></a>
## catch
- 用 catch 注册失败回调是更常见的
- 同时注册的 onRejected 只是给当前 Promise 对象注册的失败回调,它只能捕获到当前 Promise 对象的异常
- Promise 链条上的任何一个异常都会被一直向后传递,直至被捕获,catch相当于给整个 Promise 链条注册失败回调
如何中断promise链?<br />在回调函数中返回一个pendding状态的promise对象
```javascript
// 全局捕获 Promise 异常,类似于 window.onerror
window.addEventListener('unhandledrejection', event => {
const { reason, promise } = event
console.log(reason, promise)
// reason => Promise 失败原因,一般是一个错误对象
// promise => 出现异常的 Promise 对象
event.preventDefault()
}, false)
// Node.js 中使用以下方式
// process.on('unhandledRejection', (reason, promise) => {
// console.log(reason, promise)
// // reason => Promise 失败原因,一般是一个错误对象
// // promise => 出现异常的 Promise 对象
// })
四、generator,Async/Await
// 生成器函数回顾
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)
// generator.next('bar')
generator.throw(new Error('Generator error'))
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 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)
}
}
const promise = main()
promise.then(() => {
console.log('all completed')
})