1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 同步异步(概念/理解+回调函数+promise+generator+async/await+异步变同步)

同步异步(概念/理解+回调函数+promise+generator+async/await+异步变同步)

时间:2021-04-23 21:32:03

相关推荐

同步异步(概念/理解+回调函数+promise+generator+async/await+异步变同步)

异步解决疑点+异步变同步+异步同步的区别和概念

异步和同步的概念异步同步判断函数的同步异步方法 异步解决的疑点回调函数promisegeneratorasync+await 异步变同步原代码,希望实现用异步操作实现同步分析先看一下baum()函数每次next()的返回值都是什么改进后的代码补全代码 自动化实现

异步和同步的概念

异步

概念

请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕

发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式模式

非阻塞传输单位

数据包举例

callback、settimeout、ajax、回调函数、promise、then

同步

概念

提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事

发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式模式

阻塞传输单位

字符举例

js(js是单线程的,虽然js是单线程的,但是浏览器的内核是多线程的,可以通过event loop将js同步变成异步)

判断函数的同步异步方法

在结果的前后都加一个console,如果打印的结果在console中间就是同步,结果在console的后面就是异步

异步解决的疑点

回调函数

概念

回调函数就是传递一个参数化的函数,就是将这个函数作为一个参数传到另一个主函数里面,当那一个主函数执行完之后,再执行传进去的作为参数的函数。走这个过程的参数化的函数 就叫做回调函数。换个说法也就是被作为参数传递到另一个函数(主函数)的那个函数就叫做 回调函数执行回调函数的过程

1、主函数需要调用回调函数

2、中间函数登记回调函数

3、触发回调函数事件

4、调用回调函数

5、响应回调事件理解

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。

其他(apply、call)

apply:apply(this,[参数1,参数2…])

call:call(ths,参数1,参数2)代码说明

<script type="text/javascript">function title(value){//这是回调函数!!!!alert(value);}function main(title, value){//这个主函数:在参数列表中,title作为一个参数传递进来,也就是上文说的 参数化函数;然后value这个值正是title()函数中所需要的。alert("我是主函数");title(value);//结果为:'我是回调函数'。——————然后在这行这个title(),它就是回调函数咯。}main(title,"我是回调函数");//title参数加上()后,就会变回一个函数,并会被执行一次。//PS:看清楚,调用的是main()函数,意味着先执行main(),这时已经执行了主函数,title()被main()在函数体中执行了一次,因此title()是回调函数。</script>

promise

概念

(是es6新的函数体,核心是用同步的方法产生异步的效果)

Promise对象的状态有3个,分别是pending(进行中)、fulfilled(已完成)、rejected(已失败)。Promise对象一旦进入了某一个状态,就不会再转成其他状态了(主要是后面两种状态,fulfilled和rejected)。如一旦调用了resolve函数,就是fulfilled的状态,就不会再调用reject函数了。

1、pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。

2、fulfilled:满足状态,当我们回调了resolve函数时,就处于该状态。

3、rejected:拒绝状态,当我们回调了reject函数时,就处于该状态。代码格式

promise.then(function(data) {// success}).catch(function(err) {// error});

举例说明

let p = new Promise((resolve, reject) => {let a1 = '成功的参数';let a2 = '失败的参数';var time = setTimeout(() => {console.log('start');resolve(a1);reject(a2);console.log('end');}, 1000);});p.then(value => {console.log('这是resolve函数体,参数:' + value);}, reason => {console.log('这是reject函数体,参数:' + reason);})返回值startend这是resolve函数体,参数是成功的参数

.then()函数和.catch()函数

传入的数据永远是函数里面的数据,依赖于promise函数

generator

概念

ES6 新引入了 Generator 函数,可以通过 yield 关键字,把函数的执行流挂起,为改变执行流程提供了可能,从而为异步编程提供解决方案。函数的特征

– function关键字与函数名之间有一个星号 “*” (推荐紧挨着function关键字)

– 函数体内使用 yield 表达式,定义不同的内部状态 (可以有多个yield)

– 直接调用 Generator函数并不会执行,也不会返回运行结果,而是返回一个遍历器对象(Iterator Object)

– 依次调用遍历器对象的next方法,遍历 Generator函数内部的每一个状态函数的格式

// Generator函数function* generator() {yield 'status one' // yield 表达式是暂停执行的标记 return 'hello world'}let iterator = generator() // 调用 Generator函数,函数并没有执行,返回的是一个Iterator对象iterator.next() // {value: "status one", done: false},value 表示返回值,done 表示遍历还没有结束iterator.next() // {value: "hello world", done: true},value 表示返回值,done 表示遍历结束}

yield()函数和next()函数

— 每次遇到 yield,函数就暂停执行,下一次再从该位置继续向后执行;而 return 语句不具备记忆位置的功

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

async+await

概念

async 函数返回的是一个 Promise 对象。从文档中也可以得到这个信息。async 函数(包含函数语句、函数表达式、Lambda表达式)会返回一个 Promise 对象,如果在函数中 return 一个直接量,async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。

async

作为一个关键字放在函数的前面,表示该函数是一个异步函数,意味着该函数的执行不会阻塞后面代码的执行 异步函数的调用跟普通函数一样

await

await即等待,用于等待一个Promise对象。它只能在异步函数 async function中使用,否则会报错

它的返回值不是Promise对象而是Promise对象处理之后的结果

await表达式会暂停当前 async function的执行,等待Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行 async function,若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。​如果 await 操作符后的表达式的值不是一个 Promise,那么该值将被转换为一个已正常处理的 Promise。

举例

function takeLongTime() {return new Promise(resolve => {setTimeout(() => resolve("long_time_value"), 1000);});}async function test() {const v = await takeLongTime();console.log(v);}test();

返回的非promise

async function func1(){console.log('func1');var a = await func2(); //当await返回非promiseconsole.log('func1 return');}function func2(){console.log('func2');} //返回undefinedfunc1();new Promise(function(resolve){console.log('promise1');resolve('resolved');}).then(function(data){console.log(data);});结果func1func2promise1func1 returnresolved

返回的为promise

async function func1(){console.log('func1'); var a = await func2(); //当await返回promise console.log('func1 return');}async function func2(){console.log('func2');} //返回promisefunc1();new Promise(function(resolve){console.log('promise1'); resolve('resolved');}).then(function(data){console.log(data);});结果func1func2promise1func1 returnresolved

总结 async函数就是generator函数的语法糖。

async函数,就是将generator函数的*换成async,将yield替换成await。返回值是Promise。返回非Promise时,async函数会把它包装成Promise返回。(Promise.resolve(value))函数执行时,一旦遇到await就会返回。等到触发的异步操作完成(并且调用栈清空),再接着执行函数体内后面的语句。await只是让当前async函数内部、后面的代码等待,并不是所有代码都卡在这里。遇到await就先返回,执行async函数之后的代码。主线程执行过程中,遇到await后面的函数调用,会直接进入函数,并执行。

异步变同步

原代码,希望实现用异步操作实现同步

function delay(ms) {return new Promise((resolve, reject) => {setTimeout(resolve, ms);});}function* baum() {yield delay(300).then(() => console.log(1))yield console.log(2)yield delay(300).then(() => console.log(3))yield console.log(4)}const b = baum()b.next()b.next()b.next()b.next()结果2413

分析

先看一下baum()函数每次next()的返回值都是什么

const b = baum()console.log(b.next())结果{value: Promise {<pending> }, done: false }1

上面第一行输出中的value值,是delay(300).then(() => console.log(1))这段代码的执行结果,那么我们可知,对于一个promise,它的then()函数的返回值同样是一个promise对象。由此来说,只要将同步的next()执行,放到它前面异步的promise中的then()函数里,即可以达到同步代码发生在异步代码操作之后的效果了。

改进后的代码

const b = baum()b.next().value.then(() => {b.next()})结果12

是预期的效果,补全代码即可达到机械的实现效果

补全代码

const b = baum()b.next().value.then(() => {// 第一个 delay 函数返回的 promiseb.next()b.next().value.then(() => {// 第二个 delay 函数返回的 promiseb.next()})})结果1234

自动化实现

使得generator中的调用,无论异步的还是同步的yield操作,都是同步执行

function himmel(gen) {const item = gen.next()if (item.done) {return item.value}const {value, done } = itemif (value instanceof Promise) {value.then((e) => himmel(gen))} else {himmel(gen)}}测试himmel(baum())结果1234

函数的实现是一个递归,接收参数是一个generator实例,退出条件即为当yield结果中的done为true的时候。后面的代码会判断value是否是一个promise,如果是的话,就在then()方法中递归,否则就认为是同步代码,直接递归。

前端大佬太多了@~@

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。