详见链接:https://www.jianshu.com/p/79487965a0ca
Generator
- 调用 Generator 函数,返回一个遍历器对象,代表 Generator 函数的内部指针。
- 以后,每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。
- value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
generator 函数的执行方法如下:
function* gen(x) {
console.log('start')
const y = yield x * 2
return y
}
const g = gen(1)
g.next() // start { value: 2, done: false }
g.next(4) // { value: 4, done: true }
function* helloWorld () {
yield 'hello'
yield 'world'
return 'ending'
}
var hw = helloWorld()
console.log(hw) // helloWorld {<suspended>}
console.log(hw.next()) // {value: "hello", done: false}
console.log(hw.next()) // {value: "world", done: false}
console.log(hw.next()) // {value: "ending", done: false}
console.log(hw.next()) // {value: undefined, done: true}
- gen() 不会立即执行,而是一上来就暂停,返回一个 Iterator 对象
- 每次 g.next() 都会打破暂停状态去执行,直到遇到下一个 yield 或者 return
- 遇到 yield 时,会执行 yeild 后面的表达式,并返回执行之后的值,然后再次进入暂停状态,此时 done: false。
- next 函数可以接受参数,作为上个阶段异步任务的返回结果,被函数体内的变量接收
- 遇到 return 时,会返回值,执行结束,即 done: true
- 每次 g.next() 的返回值永远都是 {value: ... , done: ...} 的形式
async
https://www.jianshu.com/p/b4fd76c61dc9
async、await很好的解决了这一点,将异步强行转换为同步处理。
async函数会返回一个promise,并且Promise对象的状态值是resolved(成功的)
1、如果你没有在async函数中写return,那么Promise对象resolve的值就是是undefined
2、如果你写了return,那么return的值就会作为你成功的时候传入的值
await 等到之后,做了一件什么事情?
那么右侧表达式的结果,就是await要等的东西。
等到之后,对于await来说,分2个情况
- 不是promise对象
- 是promise对象
如果不是 promise , await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,把这个非promise的东西,作为 await表达式的结果。
如果它等到的是一个 promise 对象,await 也会暂停async后面的代码,先执行async外面的同步代码,等着 Promise 对象 fulfilled,然后把 resolve 的参数作为 await 表达式的运算结果。
- async其实就是对Generator的封装,只不过async可以自动执行next()。
- async必须等到里面所有的await执行完,async才开始return,返回的Promise状态才改变。除非遇到return和错误。
- async默认返回一个Promise,如果return不是一个Promise对象,就会被转为立即resolve的Promise,可以在then函数中获取返回值。
async function fn() {
await console.log(1111111)
await console.log(2222222)
await console.log(3333333)
}
fn()
// 1111111
// 2222222
// 3333333
async function fn () {
await 100
await 200
return 300
}
fn().then(res => {
console.log(res) // 300
})
如果在async函数中抛出了错误,则终止错误结果,不会继续向下执行:
let data1 = new Promise((resove,reject) => {
resolve('我是resolve成功的实例')
})
async function fn() {
await data1
throw new Error('我失败了')
return data1
}
fn().then(res => console.log(res)).catch(res => console.log(res));
// Error:我失败了
如果希望一个await失败,后面的继续执行,可以使用try...catch或者在await后面的Promise跟一个catch方法:
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f().then(v => console.log(v)) // hello world
// catch
async function f() {
await Promise.reject('出错了')
.catch(e => console.log(e)); // 出错了
return await Promise.resolve('hello world');
}
f().then(v => console.log(v)) // hello world
面试题
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
return 'async return';
}
async function async2() {
console.log("async2");
}
console.log("script start");
setTimeout(function() {
console.log("setTimeout");
}, 0);
async1().then(function (message) { console.log(message) });
new Promise(function(resolve) {
console.log("promise1");
resolve();
}).then(function() {
console.log("promise2");
});
console.log("script end");
/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
async return
setTimeout
*/
async function async1(){
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2(){ // 去掉了 async 关键字 返回结果相同
console.log('async2')
}
console.log('script start')
setTimeout(function(){
console.log('setTimeout')
},0)
async1();
new Promise(function(resolve){
console.log('promise1')
resolve();
}).then(function(){
console.log('promise2')
})
console.log('script end')
/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
*/
需要说明的是:
正常情况下,await命令后面是一个 Promise 对象,返回该对象的结果。如果不是 Promise 对象,就直接返回对应的值(相当于直接Promise.resolve)。
async function f() {
// 等同于
// return 123;
return await 123;
}
f().then(v => console.log(v))
// 123
其他面试题见以下链接
https://blog.csdn.net/wdhxs/article/details/110624773
网友评论