JS手写题解析

手写Promise

javascript 复制代码
class MyPromise {
  constructor(executor) { // executor执行器
    this.status = 'pending' // 等待状态
    this.value = null // 成功或失败的参数
    this.fulfilledCallbacks = [] // 成功的函数队列
    this.rejectedCallbacks = [] // 失败的函数队列
    const that = this
    function resolve(value) { // 成功的方法
      if (that.status === 'pending') {
        that.status = 'resolved'
        that.value = value
        that.fulfilledCallbacks.forEach(myFn => myFn(that.value)) //执行回调方法
      }
    }
    function reject(value) { //失败的方法
      if (that.status === 'pending') {
        that.status = 'rejected'
        that.value = value
        that.rejectedCallbacks.forEach(myFn => myFn(that.value)) //执行回调方法
      }
    }
    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }
  then(onFulfilled, onRejected) {
    if (this.status === 'pending') {
      // 等待状态,添加回调函数到成功的函数队列
      this.fulfilledCallbacks.push(() => {
        onFulfilled(this.value)
      })
      // 等待状态,添加回调函数到失败的函数队列
      this.rejectedCallbacks.push(() => {
        onRejected(this.value)
      })
    }
    if (this.status === 'resolved') { // 支持同步调用
      console.log('this', this)
      onFulfilled(this.value)
    }
    if (this.status === 'rejected') { // 支持同步调用
      onRejected(this.value)
    }
  }
}
 
// 测试
function fn() {
  return new MyPromise((resolve, reject) => {
    setTimeout(() => {
      if(Math.random() > 0.6) {
        resolve(1)
      } else {
        reject(2)
      }
    }, 1000)
  })
}
fn().then(
  res => {
    console.log('res', res) // res 1
  },
  err => {
    console.log('err', err) // err 2
  })

解析:

首先是初始化了一个Promise实例,并定义了状态、值、成功回调和失败回调,并使用that来指向调用者。

resolve函数用于执行成功回调

reject函数用于执行失败函数

try尝试执行executor函数,并传入resolve和reject,当发生err的时候捕捉err

再用then方法注册Promise成功和失败的回调函数

这边可以看下运行的顺序来更好的理解代码

首先executor(resolve,reject)会try,然后最开始肯定是pending状态,会将回调函数调到列队中。

随后settimeout启动生成random,开始执行resolve or reject

这边是调用了resolve,他会更换状态并且执行列队中的函数

res => {

console.log('res', res) // res 1

},

手写AJAX

拿下Promise后就可以趁热打铁来了解AJAX了

javascript 复制代码
// url:"url路径"  type:请求方式  data:请求参数类型  dataType:返回的字符串类型
function ajax({url,type,data,dataType}){
return new Promise(function(resolve,reject){
	//1. 创建异步请求对象
	var xhr=getXhr();
	// 备注:无需通过上面的方式,简单的创建异步请求对象的简化代码如下:
	// var xhr = window.XMLHttpRequest ? new XMLHttprequest() : new ActiveXObject('Microsoft.XMLHttp');
	//2.绑定监听事件
	xhr.onreadystatechange=function(){
		// 当异步请求状态变为4时,并且返回的状态码为200,接收响应成功
		if(xhr.readyState==4&&xhr.status==200){
			// 当返回接收的字符串类型为json串时,自动转换json串
			if(dataType!==undefined
				&&dataType.toLowerCase()==="json")
				var res=JSON.parse(xhr.responseText)
			else
				// 否则直接获取返回的响应文本中的内容
				var res=xhr.responseText
			// 通过Promise,将返回的数据向后传递,相当于获取到请求数据将数据return出来
			resolve(res);
		}
	}
	// 如果请求方式为get请求,则将请求参数拼接在url后
	if(type.toLowerCase()==="get"&&data!==undefined){
		url+="?"+data;
	}
	//3.打开连接
	xhr.open(type,url,true);
	// 如果请求方式为post请求,则修改请求消息头
	if(type.toLowerCase()==="post")
		//增加:设置请求消息头
		xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	//4.发送请求
	if(type.toLowerCase()==="post"&&data!==undefined)
		xhr.send(data);
	else
		xhr.send(null);})

首先定义了一个函数ajax,并有四个传值,这边可以看下实例,来了解参数定义

javascript 复制代码
// 定义一个函数,使用 ajax 发送请求
function fetchData() {
  // 请求配置对象,包括 url、type、data、dataType
  const config = {
    url: 'https://jsonplaceholder.typicode.com/posts/1', // 示例 API
    type: 'GET', // 请求方式,GET 或 POST
    data: null, // 请求参数,对于 GET 请求,参数直接拼接在 URL 后面
    dataType: 'json' // 返回的数据类型,这里指定为 JSON
  };

  // 调用 ajax 函数,并返回 Promise 对象
  return ajax(config)
    .then(response => {
      console.log('请求成功:', response);
      // 这里可以对获取到的数据进行进一步处理或返回
      return response;
    })
    .catch(error => {
      console.error('请求失败:', error);
      throw error; // 可以选择抛出异常或者进行其他处理
    });
}

然后rentun了一个Promise

这里面有很多可能不认识的东西,要逐一了解下

比如toLowerCase,他不会改变原字符串,可以将来的字母都转化为小写字母

JSON.parse可以将字符串转化为javascript对象,但key必须是用双引号包裹的

javascript 复制代码
let str = "Hello World";

let lowerCaseStr = str.toLowerCase();

console.log(lowerCaseStr); // 输出: "hello world"
console.log(str); // 输出: "Hello World",原始字符串未被改变
javascript 复制代码
// JSON 字符串
const jsonStr = '{"name": "John", "age": 30, "city": "New York"}';

// 使用 JSON.parse 解析 JSON 字符串
const jsonObj = JSON.parse(jsonStr);

console.log(jsonObj); // 输出: { name: 'John', age: 30, city: 'New York' }
console.log(jsonObj.name); // 输出: "John"
console.log(jsonObj.age); // 输出: 30

这样xhr.onreadystatechange里面的内容就很好理解了,就是当请求成功后将相应内容提取出来作为resolve。

相关推荐
爱吃生蚝的于勒几秒前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
binishuaio10 分钟前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE12 分钟前
【Java SE】StringBuffer
java·开发语言
就是有点傻16 分钟前
WPF中的依赖属性
开发语言·wpf
洋24024 分钟前
C语言常用标准库函数
c语言·开发语言
进击的六角龙26 分钟前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
wrx繁星点点27 分钟前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
熊的猫35 分钟前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
NoneCoder44 分钟前
Java企业级开发系列(1)
java·开发语言·spring·团队开发·开发
苏三有春44 分钟前
PyQt5实战——UTF-8编码器功能的实现(六)
开发语言·qt