Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Javascript】深入理解async/await的实现,Generator+Promise = Async/Await #3

Open
AwesomeDevin opened this issue Apr 28, 2019 · 0 comments

Comments

@AwesomeDevin
Copy link
Owner

AwesomeDevin commented Apr 28, 2019

概念

Generator 函数是 ES6 提供的一种异步编程解决方案,执行 Generator 函数会返回一个遍历器对象,也就是说,Generator 函数除了状态机,还是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。

yield表达式

形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态。

function* foo(x) {
    yield 1
    yield 2
    yield 3
    yield 4
    return 5
}

必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield表达式(或return语句)为止。换言之,Generator 函数是分段执行的,yield表达式是暂停执行的标记,而next方法可以恢复执行。

function* foo() {
    yield 1
    yield 2
    return 3
}

var f = foo()
f.next()     //{ value: 1, done: false }
f.next().value     //2
f.next()     //{ value: 3, done: true}
f.next()     //{ value: undefined, done: true}

Generator 函数已经运行完毕,next方法返回对象的value属性为3,done属性为true,之后再执行next(),done都为true,value未undefined

next方法的参数

yield表达式本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield表达式的返回值。

function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
}

var a = foo(5);
a.next() // Object{value:6, done:false}
a.next() // Object{value:NaN, done:false}
a.next() // Object{value:NaN, done:true}

var b = foo(5);
b.next() // { value:6, done:false }
b.next(12) // { value:8, done:false }
b.next(13) // { value:42, done:true }

Generator + Promise = 强大的异步回调方式

没有回调
function sayhello() {
    setTimeout(()=>{
        console.log(123)
    },3000)
}

function helloworld() {
    const data =  sayhello();
    console.log(data);
    console.log(456)
}
helloworld()

这里写图片描述

使用async/await

function sayhello(){
	return new Promise((resolve)=>{
		setTimeout(()=>{
			resolve(123)
	        console.log(123)
	    },3000)
	})
}

async helloworld(){
    const data = await sayhello()
    console.log(data)
    console.log(456)
}
使用Generator + Promise 实现async/await
function co(gen) {
    if(!gen) return
	return new Promise((resolve,reject)=>{
		var it = gen();
		try{
			function step(next){
				if(next.done)
				{
					return resolve(next.value)
				}
				else{
					Promise.resolve(next.value).then((res)=>{
						return step(it.next(res))
					},(e)=>{
						return step(it.throw(e))
					})
				}
			}
			step(it.next())
		}
		catch(e){
			return reject(e)
		}
	})
}

function sayhello(){
       // 之所以需要返回一个 promise ,是因为 co 函数会在底层使用 promise 同步执行 sayhello ,为了保证 sayhello 同步执行完该异步函数后获取到正确的返回值,需要使用promise包裹返回值。
	return new Promise((resolve)=>{
		setTimeout(()=>{
			resolve(123)
	        console.log(123)
	    },3000)
	})
}

co(
	function* helloworld(){
		const data = yield sayhello()
		console.log(data)
		console.log(456)
	}
)

这里写图片描述

可以看到,通过Generator + Promise(async/await)我们已经拿到了延时器中的数据。

任何复杂的异步功能都可以被promise搞定,而且你还可以用generator把这些流程写的像同步代码一样。只要你让yield返回一个promise。

@AwesomeDevin AwesomeDevin changed the title 【通俗易懂】手把手进行ES6异步编程: Generator + Promise = JavaScript强大的异步回调方式 【Javascript】手把手进行ES6异步编程: Generator + Promise = JavaScript强大的异步回调方式 Apr 28, 2019
@AwesomeDevin AwesomeDevin changed the title 【Javascript】手把手进行ES6异步编程: Generator + Promise = JavaScript强大的异步回调方式 【Javascript】手把手进行ES6异步编程: Generator+Promise=Async/Await Apr 30, 2019
@AwesomeDevin AwesomeDevin changed the title 【Javascript】手把手进行ES6异步编程: Generator+Promise=Async/Await 【Javascript】手把手进行ES6异步编程: Generator+Promise=Async/Await Apr 30, 2019
@AwesomeDevin AwesomeDevin changed the title 【Javascript】手把手进行ES6异步编程: Generator+Promise=Async/Await 【Javascript】手把手进行ES6异步编程: Generator+Promise = Async/Await Apr 30, 2019
@AwesomeDevin AwesomeDevin changed the title 【Javascript】手把手进行ES6异步编程: Generator+Promise = Async/Await 【Javascript】深入理解async/await的实现,Generator+Promise = Async/Await Apr 30, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant