Skip to main content

promise

· 4 min read

简单的promise

时间长了对promise原理慢慢有些生疏,记录实现一个简易的promise加强理解。

// 定义 Promise 的三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

class MyPromise {
constructor(executor) {
// 初始状态为 pending
this.status = PENDING;
// 存储成功的值
this.value = undefined;
// 存储失败的原因
this.reason = undefined;
// 存储成功回调
this.onFulfilledCallbacks = [];
// 存储失败回调
this.onRejectedCallbacks = [];

const resolve = (value) => {
if (this.status === PENDING) {
this.status = FULFILLED;
this.value = value;
// 依次执行成功回调
this.onFulfilledCallbacks.forEach((callback) => callback());
}
};

const reject = (reason) => {
if (this.status === PENDING) {
this.status = REJECTED;
this.reason = reason;
// 依次执行失败回调
this.onRejectedCallbacks.forEach((callback) => callback());
}
};

try {
// 执行 executor 函数,传入 resolve 和 reject
executor(resolve, reject);
} catch (error) {
// 如果 executor 执行出错,调用 reject
reject(error);
}
}

then(onFulfilled, onRejected) {
// 处理 onFulfilled 不是函数的情况
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
// 处理 onRejected 不是函数的情况
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason; };

const newPromise = new MyPromise((resolve, reject) => {
const handleFulfilled = () => {
try {
const x = onFulfilled(this.value);
// 处理 then 方法返回值,根据规范判断是否递归解析
resolvePromise(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
};

const handleRejected = () => {
try {
const x = onRejected(this.reason);
// 处理 then 方法返回值,根据规范判断是否递归解析
resolvePromise(newPromise, x, resolve, reject);
} catch (error) {
reject(error);
}
};

if (this.status === FULFILLED) {
// 如果状态已经是 fulfilled,异步执行成功回调
setTimeout(handleFulfilled, 0);
} else if (this.status === REJECTED) {
// 如果状态已经是 rejected,异步执行失败回调
setTimeout(handleRejected, 0);
} else if (this.status === PENDING) {
// 如果状态还是 pending,将回调存储起来
this.onFulfilledCallbacks.push(() => setTimeout(handleFulfilled, 0));
this.onRejectedCallbacks.push(() => setTimeout(handleRejected, 0));
}
});

return newPromise;
}
}

function resolvePromise(promise, x, resolve, reject) {
if (promise === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}

let called = false;

if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
then.call(
x,
(y) => {
if (called) return;
called = true;
// 递归解析返回的 promise
resolvePromise(promise, y, resolve, reject);
},
(r) => {
if (called) return;
called = true;
reject(r);
}
);
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}

// 以下是测试代码
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000);
});

promise.then((value) => {
console.log('First then:', value);
return value * 2;
}).then((value) => {
console.log('Second then:', value);
return new MyPromise((resolve) => {
setTimeout(() => {
resolve(value + 50);
}, 1000);
});
}).then((value) => {
console.log('Third then:', value);
});

//导出模块,为测试准备
module.exports = MyPromise;

-安装 ‘promises-aplus-tests’测试工具,并暴露测试适配器

// test.js
const MyPromise = require('../src/somecode/myPromise');

// 包装 MyPromise 以符合测试工具的要求
const adapter = {
resolved: function (value) {
return new MyPromise((resolve) => resolve(value));
},
rejected: function (reason) {
return new MyPromise((_, reject) => reject(reason));
},
deferred: function () {
let resolve, reject;
const promise = new MyPromise((res, rej) => {
resolve = res;
reject = rej;
});
return {
promise,
resolve,
reject
};
}
};

module.exports = adapter;

终端输入 npx '工具名' 文件名 ’

最终结果: 872 passing (16s)

axios

· 3 min read

easy Axios

axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js 环境。简单的实现支持基本的 HTTP 请求方法(如 GET、POST),并能处理请求和响应,目的是为了了解其实现方法。

// 创建一个 Axios 类,用于封装 HTTP 请求的逻辑
class Axios {
// 构造函数,初始化默认配置
constructor() {
// 可以在这里添加更多的默认配置,如超时时间、请求头默认值等
this.defaults = {
baseURL: '',
headers: {
'Content-Type': 'application/json'
}
};
}

// 发送请求的核心方法
request(config) {
// 合并默认配置和用户传入的配置
const mergedConfig = { ...this.defaults, ...config };
const { url, method = 'GET', headers, data } = mergedConfig;

// 返回一个 Promise 对象,用于处理异步请求
return new Promise((resolve, reject) => {
// 创建一个 XMLHttpRequest 对象,用于发送 HTTP 请求
const xhr = new XMLHttpRequest();

// 打开一个请求,设置请求方法和请求 URL
xhr.open(method.toUpperCase(), url, true);

// 设置请求头
for (const header in headers) {
if (headers.hasOwnProperty(header)) {
xhr.setRequestHeader(header, headers[header]);
}
}

// 监听请求状态变化事件
xhr.onreadystatechange = function () {
// 当请求完成且状态码为 200 时,表示请求成功
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status >= 200 && xhr.status < 300) {
// 解析响应数据
let responseData;
try {
responseData = JSON.parse(xhr.responseText);
} catch (error) {
responseData = xhr.responseText;
}
// 构建响应对象
const response = {
data: responseData,
status: xhr.status,
statusText: xhr.statusText,
headers: xhr.getAllResponseHeaders(),
config: mergedConfig
};
// 解决 Promise,返回响应对象
resolve(response);
} else {
// 请求失败,拒绝 Promise 并返回错误信息
reject(new Error(`Request failed with status code ${xhr.status}`));
}
}
};

// 监听请求错误事件
xhr.onerror = function () {
// 请求发生网络错误,拒绝 Promise 并返回错误信息
reject(new Error('Network Error'));
};

// 发送请求,如果有数据则将数据作为请求体发送
xhr.send(data ? JSON.stringify(data) : null);
});
}

// 封装 GET 请求方法
get(url, config = {}) {
return this.request({ ...config, method: 'GET', url });
}

// 封装 POST 请求方法
post(url, data = {}, config = {}) {
return this.request({ ...config, method: 'POST', url, data });
}
}

// 创建一个 axios 实例,方便使用
const axios = new Axios();

// 示例使用
// 发送一个 GET 请求
axios.get('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
console.log('GET Response:', response.data);
})
.catch(error => {
console.error('GET Error:', error.message);
});

// 发送一个 POST 请求
axios.post('https://jsonplaceholder.typicode.com/posts', {
title: 'foo',
body: 'bar',
userId: 1
})
.then(response => {
console.log('POST Response:', response.data);
})
.catch(error => {
console.error('POST Error:', error.message);
});