一、异步和单线程
1. 同步和异步的区别是什么?
答案: 同步会阻塞代码执行;异步不会阻塞代码执行。
解析:
什么是单线程?
- JS是单线程语言,只能同时做一件事。
- 浏览器和nodejs已支持JS启动进程。
- JS和DOM渲染共用同一个线程,因为JS可修改DOM结构(JS执行时,DOM停止渲染;DOM渲染时,JS停止执行)
为什么需要异步?(异步时基于callback回调函数形式调用的 )
- 遇到等待,如网络请求和定时任务时不能卡住
异步和同步的区别?
- 基于JS是单线程语言
- 异步不会阻塞代码执行
- 同步会阻塞代码执行
应用场景
- 网络请求,如ajax图片加载js
//ajax console.log('start'); $.get('./data1.json', function(data1) { console.log(data1); }) console.log('end'); // 图片加载 console.log('start'); let img = document.createElement('img') img.onload = function() { console.log('loaded'); } img.src = './xxx.png' console.log('end');
- 定时任务,如setTimeout、setIntervaljs
// setTimeout console.log(100); setTimeout(function() { console.log(200); }, 1000) console.log(300); // setInterval console.log(100); setInterval(function() { console.log(200); }, 1000) console.log(300);
callback hell
和promise
promise
的形式是一个管道式的串联形式,回调函数都放在then中;与传统的嵌套形式不同。- 实现Promise的思路
promise是一个构造函数,其接受一个函数作为参数;作为参数的函数里,有两个方法resolve和reject;promise带有方法then和catch。我们需要调用resovle和reject方法去改变状态, resolve调用意味着异步请求已经有了结果,可以执行then里面的回调了。
- Promise有哪几种状态?从一种状态到另一种状态还能不能再改变?
回答:有pending(初始状态)、fulfilled(成功状态)、rejected(失败状态)三种状态。 Promise的含义为承诺,这个承诺一旦从等待状态变成为其他状态就永远不能更改状态了。 pending:等待状态,比如正在进行网络请求,或者定时器没有到时间。 fulfill:满足状态,当我们主动回调了resolve时,就处于该状态,并且会回调.then() reject:拒绝状态,当我们主动回调了reject时,就处于该状态,并且会回调.catch()。
- Promise的then返回什么?
- then方法的返回结果是Promise对象,对象状态由回调函数的执行结果决定。因此可以使用链式调用解决回调地狱的问题。
- 实现Promise的思路
- 网络请求,如ajax图片加载
2. 手写Promise
加载一张图片
- then中箭头函数的参数img是由resolve传入的
- then方法中return的返回值会传递到第二个then里js
//promise基本使用 function loadImg(src) { const p = new Promise( (resolve, reject) => { const img = document.createElement('img') img.onload = () => { resolve(img) //img参数由then接收 } img.onerror = () => { const err = new Error(`图片加载失败${src}`) reject(err) } img.src = src } ) return p } const url = 'https://picnew7.photophoto.cn/20130416/dahaishatanhaidaotupian-11521953_1.jpg' loadImg(url).then(img => { console.log(img.width); return img //这个return会传到第二个then里 }).then(img => { console.log(img.height); }).catch(ex => console.error(ex))
- 链式引用promise,解决回调地狱问题js
function loadImg(src) { const p = new Promise( (resolve, reject) => { const img = document.createElement('img') img.onload = () => { resolve(img) //img参数由then接收 } img.onerror = () => { const err = new Error(`图片加载失败${src}`) reject(err) } img.src = src } ) return p } // 怎么使用串行方式解决回调地狱? const url1 = 'https://picnew7.photophoto.cn/20130416/dahaishatanhaidaotupian-11521953_1.jpg' const url2 = 'https://static2.cbrimages.com/wordpress/wp-content/uploads/2021/04/luffy-feature-image.jpg' loadImg(url1).then(img1 => { console.log(img1.width); return img1 //普通对象 }).then(img1 => { console.log(img1.height); return loadImg(url2) //promise实例 }).then(img2 => { console.log(img2.width); return img2 }).then(img2 => { console.log(img2.height); }).catch(ex => console.error(ex))
3. 前端使用异步的场景有哪些?
答案: 网络请求,如ajax图片加载;定时任务,如setTimeout、setInterval。