promise背景、规范、手写

promise出现的原因

  1. 异步执行
  2. 循环执行 + 循环终止(时延的存在)

计算机原理

进程和线程的概念和区别:

  1. 进程:是CPU资源分配的最小单位,享有独立资源,可协同多个线程来完成上级CPU的命令。即,进程执行CPU命令时,是分配给多个线程去执行任务的。
  2. 线程:是CPU调度的最小单位,与其他线程一起共享各个进程的资源,多个线程合作完成进程的命令。

面试题:

  1. Chrome新开一个窗口,新开的tab页是属于进程还是线程?属于一个进程,可以从进程的概念开始说起。
    浏览器开启了多个TAB页,多个TAB页是多个进程,一个个TAB页去分配多个线程执行任务。
    CPU分配给进程资源时,应用根据需要开启线程。
  2. 窗口(进程间)通信通过什么?浏览器的存储storage、cookie。=>可能问到多种存储的区别。=>可能问到浏览器的原理。

浏览器原理

  1. GUI渲染引擎:
    1. 任务:完善页面骨架。解析HTML、CSS,构建DOM树,然后进行布局、绘制。
    2. 特点:与JS引擎互斥,当执行JS引擎线程时,GUI会pending(挂起),当任务队列空闲时,才会继续执行GUI。
  2. JS引擎:
    1. 任务:处理JS,解析执行脚本;分配、处理、执行待执行的事件,使用event队列。
    2. 特点:阻塞GUI渲染。
  3. 定时器触发引擎:
    1. 任务:异步定时器处理与执行。接收JS引擎分配的定时器任务并计数。处理完成后交予事件触发线程触发。
  4. 异步HTTP请求线程:
    1. 任务:异步执行请求类处理(Promise/ajax等)。接收JS引擎分配的异步HTTP请求。监听回调,交予事件触发线程触发。
  5. 事件触发引擎:
    1. 接收来源:定时器、异步、用户操作。
    2. 任务:将回调过来的事件依次接入到任务队列的队尾,然后还给JS引擎。

JS执行原理(浏览器工作流程)

  1. Memory Heap(存储堆):分配内存。相当于一个仓库,存储所有代码。
  2. Call Stack():执行回调。存储所有即将要执行的代码。

与WebAPI进行交互。

JS任务分类:
纵向分类:(优先级:宏 > 微,有微则微,无微则宏)

  1. 宏任务macro:script、setTimeout、setInterval、I/O。
  2. 微任务micro:new Promise(){}.then()、webAPI。
    在这里插入图片描述

横向分类:

  1. 同步:直接进入主线程
  2. 异步:先进入event table、event queue,等主线程为空再执行。

面试题:

  1. Event Loop问题:JS是单线程预约,单步执行。JS堆栈的执行顺序与堆栈溢出 => 性能优化。执行顺序题。
  2. 写一个异步请求函数。
request.onreadystatechange = () => {
	if(request.readyState === 4) {
		const _status = request.status;
		if(_status === 200) {
			const _res = request.responseText;
			return success(_res);
		}else {
			return fail(_status);
		}
	}
}

Promise规范及应用

Promise出现的原因:拯救回调导致的无穷嵌套。
Promise的特点:

  1. 多个异步顺序执行。=>链式调用p.then().then()…
  2. 全部执行完成后再操作。=>Promise.all([promise1, …]).then(res => {…})
  3. 一旦有执行完成的立刻操作。=>Promise.race([promise1, …]).then(res => {…})

描述Promise框架:(即Promise规范,面试常考)

  1. Promise的状态:pending、fulfilled、rejected
  2. new Promise执行器executor(),执行器参数是resolve、reject。
  3. promise的默认状态:pending。
  4. promise状态的流转:promise=>resolve,promise=>fulfilled。
  5. promise保存成功状态的枚举(value值):undefined、thenable、promise。
  6. promise保存失败状态的值(reason):reason保存失败,描述promise接口。
  7. promise一定会有then,then的接收来源:onFulfilled(value) + onRejected(reason)。

手写Promise

//三个状态:PENDING FULFILLED REJECTED
const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';

class Promise {
	constructor(executor) {
		// 默认状态的处理: PENDING
		this.status = PENDING;
		// 成功状态的值
		this.value = undefined;
		// 失败状态的值
		this.reason = undefined;
		
		// 存放成功的回调
		this.onResolvedCallbacks = []
		// 存放失败的回调
		this.onRejectedCallbacks = []
		
		// 成功状态的回调
		let resolve = value => {
			if(this.status === PENDING) {
				this.status = FULFILLED;
				this.value = value;
				
				// 依次调用对应函数的执行
				(this.onResolvedCallbacks || []).forEach(fn => fn())	
			}
		};
		// 失败状态的回调
		let reject = reason => {
			if(this.status === PENDING) {
				this.status = REJECTED;
				this.reason = reason;
				
				// 依次调用对应函数的执行
				(this.onRejectedCallbacks || []).forEach(fn => fn())	
			}
		}
		
		try {
			executor(resolve, reject);
		}catch(error) {
			reject(error);
		}
	}
	
	then(onFulfilled, onRejected) {
		if(this.status === FULFILLED) {
			onFulfilled(this.value)
		}
		if(this.status === REJECTED) {
			onRejected(this.reason)
		}
		if (this.status === PENDING) {
			this.onResolvedCallbacks.push(() =>{
				onFulfilled(this.value)
		})
			this.onRejectedCallbacks.push(() => {
				onRejected(this.reason)
			})
		}
	}
}

async await

比promise更进一步解决回调的问题,像是把异步代码按照同步的方式来写,执行时才异步。如下,promise方式还是会出现相互嵌套的问题,但是async await则不会,看起来更为简便清晰。

// promise方式
function wait500(input) {
    return new Promise((resolve, reject) => {
      console.log('wait500', input)
      setTimeout(() => {
        resolve(input + 500)
      }, 500);
    });
}
wait500.then(res => {
  wait500.then(res => {
    wait500.then(res => {
      wait500.then(res => {
      })
    })
  })
})

// async & await方式
async function asyncCall() {
	const result = await wait500(0);
	result = await wait500(0);
	result = await wait500(0);
	result = await wait500(0);
	console.log('asyncCall', result);
}
asyncCall();

generator

使用步进的方式代替then。例如当Ajax不知道需要执行多少时间时,使用generator方式会比promise更为准确。

function * generator() {
	let index = 0;
	while(true)
		yield index++;
}
let gen = generator();
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);

面试重点:
结合流水线对generator做自动化处理。

const GEN_LINE = [1,2,3,4,5,6];
(GEN_LINE || []).forEach(i => {
	console.log(gen.next(i).value);
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值