Promise & Generator
2021-04-25 本文已影响0人
丽__
为了解决回调地域问题,commonJS社区提出了Promise规范,在es5中被标准化,成为语言规范
image.png image.png- 安装对应版本的webpack
"html-webpack-plugin": "^3.2.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
使用npx webpack-dev-server promise/01.js --open 只有可以自动打开浏览器F12查看运行结果
---package.json
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'none',
stats: 'none',
devtool: 'source-map',
plugins: [
new HtmlWebpackPlugin()
]
}
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')
输出结果
image.png
- Promise 方式的AJAX
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('../promise/api/users.json').then(function (res) {
console.log(res)
}, function (error) {
console.log(error);
})
- Promise对象的then方法会返回一个全新的Promise对象
- 后面的then方法就是在为上一个then返回的Promise注册回调
- 前面then方法中回调函数的返回值会作为后面then方法回调的参数
- 如果回调中返回的是Promise,那么后面的then方法的回调会等待它的结束
链式调用 then
ajax('../promise/api/users.json').then(function (value) {
console.log(111);
}).then(function () {
console.log(222);
}).then(function () {
console.log(33);
})
// 从前往后依次执行
没一个then方法都是上一个then返回的promise对象添加状态明确过后的回调
- Promise 异常处理 catch
ajax('../promise/api/usersd.json').then(function (value) {
console.log(111);
}).catch(function (error) {
console.log(error);
})
- Promise 静态方法
//成功
Promise.resolve('foo').then(function(value){
console.log(value);
})
等价于
new Promise(function(resolve,refect){
resolve('foo')
})
//失败
Promise.reject(new Error('rejected')).catch(function(error){
console.log(error);
})
//相等
var promise =ajax('../promise/api/users.json')
var promise2 = Promise.resolve(promise)
console.log(promise === promise2);
// true
- Promise 并行执行(promise.all)
var promise = Promise.all([
ajax('../promise/api/users.json'),
ajax('../promise/api/users2.json'),
])
promise.then(function (values) {
console.log(values);
}).catch(function (error) {
console.log(error);
})
//其中有一个返回失败 整体都失败
ajax('../promise/api/url.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()
区别:all :等待所有任务结束
race:只会等待第一个任务结束 -
Promise 执行时序 宏任务 微任务
console.log('start');
setTimeout(()=>{
console.log('setTimeout');
},0)
Promise.resolve().then(()=>{
console.log('promise')
}).then(()=>{
console.log('promise2');
}).then(()=>{
console.log('promise3');
})
console.log('end');
//输出 结果
start
end
promise
promise2
promise3
setTimeout
回调队列中的问题称之为宏任务,宏任务执行过程中可能临时加上一些额外的需求,可以选择作为一个新的宏任务进到队列中排队,也可以作为当前任务的微任务,直接在当前任务结束过后立即执行 ,Promise的回调会作为微任务执行,setTimeout作为宏任务执行。 微任务的目的是为了提高整体的响应能力,目前绝大多数异步调用都是作为宏任务执行,Promise & MutationBoserver,node中的process.nextTick都是微任务
- 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);
generator.next('bar');
generator.throw(new Error('Generator error'))
输出结果
image.png
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();
})
}
function* main() {
try {
const users = yield ajax('../promise/api/users.json')
console.log(users);
const users2 = yield ajax('../promise/api/users2.json')
console.log(users2);
} 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)
// co库:https://github.com/tj/co
- Async / Await 语法糖(语言层面的异步编程标准)
async function main() {
try {
const users = await ajax('../promise/api/users.json')
console.log(users);
const users2 = await ajax('../promise/api/users2.json')
console.log(users2);
} catch (e) {
console.log(e)
}
}
//直接调用
main()