- ECMAScript 和 JavaScript 的关系是,前者是后者的规格,后者是前者的一种实现
- ES6 这个词的原意,就是指 JavaScript 语言的下一个版本
- ES6 既是一个历史名词,也是一个泛指,含义是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 8 9 等等
- 可以将 ES6 代码转为 ES5 代码,从而在现有环境执行。这意味着,你可以用 ES6 的方式编写程序,又不用担心现有环境是否支持
set.size:类似于length 长度
add(value):添加某个值,返回 Set 结构本身
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。
map.set(key,val)
map.get(key)
map.has()
在 JavaScript 中,所有代码都是单线程的,也就是同步执行的。而 Promise 就
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
Promise 对象用于表示一个异步操作的最终完成(或失败),及其结果值。为异步编程提供了一种解决方案。
Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
Promise对象的状态,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected。
Promise 对象是由 关键字 new 构造函数来创建的。
let p = new Promise((resolve, reject)=> {
//做一些异步操作
setTimeout(()=> {
console.log('执行完成');
resolve('可以任何数据例如接口返回数据');
}, 1000);
});
//执行结果:执行完成
//执行过程:执行一个异步操作,也就是setTimeout,1秒后,输出“执行完成”,并且调用resolve方法。
注意!我只是new了一个对象,并没有调用它,就已经执行了。所以用Promise的时候一般是包在一个函数中,在需要的时候去运行这个函数。
<button onclick="promiseClick()">开始异步</button>
<script>
const promiseClick = () => {
return new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log('执行完成');
resolve('可以任何数据例如接口返回数据');
}, 1000);
});
}
</script>
//刷新页面的是没有执行的,点击后控制台打出。
//执行:执行完成
1、为什么要放在函数里面
2、resolve是个什么
我们包装好的函数后,会 return 出 Promise 对象,执行这个函数我们得到了一个Promise对象。接下来就可以用Promise对象上的then、catch方法了,这就是Promise的强大之处了。
promiseClick().then((data)=>{
console.log(data);
//后面可以用传过来的数据做些其他操作
//......
})
//执行:执行完成
//resolve('xx');中的内容或数据
首先方法被调用执行了promise,最后执行了promise的then方法,then方法是一个函数接受一个参数是resolve返回的数据;就输出了 resolve 中内容。
then里面的函数就是回调函数,能够在promiseClick这个函数异步任务执行完成后被执行。这就是Promise的作用。简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。
那么,如果有多层回调该怎么办?
而Promise的优势在于可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。
所以:Promise能够简化层层回调的写法 Promise的精髓是“状态”,用维护状态、传递状态的方式来使得回调函数能够及时调用,优点简单、灵活。
//函数返回promise对象
let a = ()=>{
return new Promise((r, j) => {
setTimeout(() => {
r("a数据");
}, 2000)
})
}
//函数返回promise对象
let b = ()=>{
return new Promise((r, j) => {
setTimeout(() => {
//使用数据
// console.log("bbb" + data);
r("b数据");
}, 1000)
})
}
//有了以上执行函数,用一个Promise对象来执行它们
let sum = ()=>{
return new Promise((r, j) => {
setTimeout(() => {
r("第一");
}, 500)
})
}
//执行
sum().then((sum)=>{
console.log(sum);
return a();
})
.then((aa)=>{
console.log(aa);
return b();
}).then((bb)=>{
console.log(bb);
})
.catch((err) => {
console.log(err); // err 输出 j("失败信息")
})
//执行:第一
// a数据
// b数据
这样按顺序,每个异步回调成功后的内容,在sum中传给resolve的数据,能在接下来的then方法中拿到依次类推。
以上是resolve用法进行了解释,resolve是对promise成功时候的回调,它把promise的状态修改为
fullfiled(已成功)。
在 then中可以传两个参数。
then方法可以接受两个参数分别是函数,第一个对应resolve的回调,第二个对应reject的回调。所以我们能够分别拿到回调函数中成功的数据和失败的原因,并不会卡死 Js 代码运行。
//执行
sum().then((sum)=>{
console.log(sum);
return a();
},(err)=>{
console.log(err); // j("失败内容")
})
.then...
reject 就是失败的时候的回调,他把promise的状态修改为 rejected,这样我们在 catch 中就能捕捉到,然后执行“失败”情况的回调。
//执行
.catch((err) => {
console.log(err);
})
与then同级的另一个方法,该方法提供了并行执行异步的操作,在所有异步操作执行完且执行结果都是成功的时候才执行。
let a = ()=>{
return new Promise((r, j) => {
setTimeout(() => {
r("aaa数据");
}, 1000)
})
}
let b = ()=>{
return new Promise((r, j) => {
setTimeout(() => {
r("bbb数据");
//j("失败了")
}, 1000)
})
}
Promise.all([a(),b()])
.then((result) => {
console.log(result);
}).catch((err) => {
console.log(err);
});
使用 Promise.all 来执行,all接收一个数组参数,这组参数为需要执行异步操作的所有方法,里面的值最终都算返回Promise对象。
异步操作是并行执行的,等到它们都执行完后才会进到then里面。all会把所有异步操作的结果放进一个数组中传给then,然后再执行then方法的成功回调将结果接收。
应用场景:比如你需要提前准备好所有数据才渲染页面时就可以使用all,执行多个异步操作将所有的数据处理好,再渲染。
all是所有的异步操作都执行完再执行then方法,那么race方法就是相反的,谁先执行完成就先执行回调。先执行完的不管是进行了race的成功回调还是失败回调,其余的将不会再进入race的任何回调。
(赛跑规则)
let a = () => {
return new Promise((r, j) => {
setTimeout(r,300,'r-300');
})
}
let b = () => {
return new Promise((r, j) => {
setTimeout(r,100,'r-100');
})
}
Promise.race([a(), b()])
.then((result) => {
console.log(result);
}).catch((err) => {
console.log(err);
});
//执行:r-100
Generator 函数是一个普通函数。
function * helloWorldGenerator() {
yield console.log('hello');
yield console.log('world');
return console.log('ending');
}
var hw = helloWorldGenerator();
— 控制台输入 hw.next();
hw.next();
index.html:156 hello
hw.next();
index.html:157 world
hw.next();
index.html:158 ending
必须调用遍历器对象的 next() 方法,使得指针移向下一个状态。每次调用next方法,内部指针就从上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。
换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。
上面代码定义了一个 Generator 函数helloWorldGenerator,它内部有两个yield表达式(hello和world),即该函数有三个状态:hello,world 和 return 语句(结束执行)。
由于 Generator 函数返回的遍历器对象,只有调用next方法才会遍历下一个内部状态,所以其实提供了一种可以暂停执行的函数。yield表达式就是暂停标志。
(1)遇到yield表达式,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield表达式。
(3)如果没有再遇到新的yield表达式,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。
yield表达式后面的表达式,只有当调用next方法、内部指针指向该语句时才会执行,因此等于为 JavaScript 提供了手动的“惰性求值”(Lazy Evaluation)的语法功能。
ajax的异步处理,需要等待别的异步成功后再执行
function* main() {
...
var result = yield request("http://www.xxx.com?rows=10&f={firstName}");
console.log(result);
//do 别的ajax请求;
}
co是用来自动执行generator函数的工具。generator的好处是可以在定义函数时候就打上“断点”,调用函数时候可以在断点的地方暂停函数的执行。Generator带来的问题是如何控制什么时候进行下一步调用。co可以解决这个问题。
1、co 模块,它基于 ES6 的 generator 和 yield ,能用同步的形式编写异步代码的nodejs模块。
代码如下:
const co = require ('co');
function* main() {
执行代码。。。
});
co(main);
co 模块可以将异步解改成同步。co 函数接受一个 generator 函数作为参数,在函数内部自动执行 yield 。
需要yield后面的数据类型为:
最后两种类型是官方建议避免使用的。
安装:
$ npm install co
index.js
function* helloWorldGenerator() {
var a = Promise.resolve(1);
var b = Promise.resolve(2);
var c = Promise.resolve(3);
var res = yield [a, b, c];
console.log(res);
}
co(helloWorldGenerator).catch(onerror);
// 执行: [1, 2, 3]
function onerror(err) {
console.error(err);
}