axios和fetch区别
二者都用来发送ajax请求,实现局部更新,axios是基于xhr的,fetch是原生支持的。
axios的拦截器是什么?有什么用?
interceptors.request可以做身份验证
interceptors.response可以做error日志处理,统一返回格式(res.data和res.data.data统一为res.data)
const instance = axios.create({
baseURL: 'https://api.example.com',
timeout: 1000,
headers: {
'Content-Type': 'application/json'
}
})
// 类似express中的app.use,可以做身份验证
instance.interceptors.request.use(
function(config){
const token=localStorage.getItem('token')
if(token){
config.headers.Authorization=`Bearer ${token}`
}
return config
}
function(error){
return Promise.reject(error)
}
)
// 可以用来统一处理error日志,而不是在每个catch中处理
axios.interceptors.response.use(
response => {
// 处理成功的响应
console.log('Response received:', response);
// 例如统一处理数据格式
if (response.data && response.data.data) {
return response.data.data;
}
return response;
},
error => {
// 处理错误的响应
console.error('Error response:', error);
// 例如统一处理错误信息
if (error.response) {
switch (error.response.status) {
case 401:
// 处理未授权错误
console.error('Unauthorized');
break;
case 500:
// 处理服务器错误
console.error('Server error');
break;
default:
console.error('Error status:', error.response.status);
break;
}
}
return Promise.reject(error);
}
);
axios还有哪些方法?
axios.get, axios.post, axios.options(预检), axios.patch修改
axios.all(类似promise.all)
组合模式与继承
为什么组合大于继承?
这是在功能不够确定时,组合大于继承。
例如人类在建立鸟的分类系统时,如果使用单继承,就类似文件夹分类。
abstract class Bird {
fly() {
console.log('fly')
}
}
鸟分为麻雀、天鹅、鹈鹕等,但有些鸟会飞,有些不会。如果鸡继承鸟的话,就会有会飞这个方法,但鸡不会飞,为了避免误用,就需要抛出异常:
class chicken extends Bird {
fly() {
throw new Error("cannot fly")
}
}
或者分为两个类,
abstract class Bird {}
class FlyableBird {
fly() {
console.log('fly')
}
}
class UnFlyableBird {}
但后来随着种类增多,可能会有生殖方式、寿命、迁徙、地域、嘴巴形状、眼睛形状等等区分,这个继承层级或者说文件夹的深度会变得越来越深。
这种情况可以选择组合模式,类似标签。
interface Flyable {
fly(): void;
}
interface EggLayable {
layEgg(): void;
}
但这样我们就会每次都需要实现fly方法,为了减少重复代码,可以使用委托:
interface Flyable {
fly(): void;
}
interface Tweetable {
tweet(): void;
}
interface EggLayable {
layEgg(): void;
}
class FlyAbility implements Flyable {
fly() {
console.log("I can fly!");
}
}
class TweetAbility implements Tweetable {
tweet() {
console.log("I can tweet!");
}
}
class EggLayAbility implements EggLayable {
layEgg() {
console.log("I can lay an egg!");
}
}
class Ostrich implements Tweetable, EggLayable {
private tweetAbility: TweetAbility;
private eggLayAbility: EggLayAbility;
constructor() {
this.tweetAbility = new TweetAbility();
this.eggLayAbility = new EggLayAbility();
}
tweet() {
this.tweetAbility.tweet();
}
layEgg() {
this.eggLayAbility.layEgg();
}
}
class Sparrow implements Flyable, Tweetable, EggLayable {
private flyAbility: FlyAbility;
private tweetAbility: TweetAbility;
private eggLayAbility: EggLayAbility;
constructor() {
this.flyAbility = new FlyAbility();
this.tweetAbility = new TweetAbility();
this.eggLayAbility = new EggLayAbility();
}
fly() {
this.flyAbility.fly();
}
layEgg() {
this.eggLayAbility.layEgg();
}
}
柯里化
什么是柯里化?柯里化有什么用?
real world haskell中的“Partial Function Application and Currying”章节有讲到:“In Haskell, all functions take only one argument.”
ghci> :type dropWhile
dropWhile :: (a -> Bool) -> [a] -> [a]
ghci> :type dropWhile isSpace
dropWhile isSpace :: [Char] -> [Char]
dropWhile isSpace is a function that strips leading whitespace from a string.
How is this useful? As one example, we can use it as an argument to a higher order function:
ghci> map (dropWhile isSpace) [" a","f"," e"]
["a","f","e"]”
bind和curry同样是partial application,有什么不同?
bind需要绑定context,curry不需要。
TODO: 在解决这个问题之前,我们可以看一下bind的实现:
==和===有什么不同?
5=='5' // '5'会被转换为number 5
0 == false // false会被转换为0
null == undefined // true,因为它们在不进行类型转换的情况下是相等的
null === undefined // false,因为类型不同,null是object类型,undefined是undefined
console.log(typeof a); // 输出:object
console.log(typeof b); // 输出:undefined
Array API
let L=console.log.bind(console)
let arr=[1,2,3,4]
L(arr.some(curr=> curr==2 || curr==3)) // true
L(arr.every(curr=> curr >0)) // true
L(arr.every(curr=> curr >1)) // false
let total=0
arr.forEach((v,i)=>{
total+=v
})
L(total) // 10
L(arr.indexOf(4))
L(arr.find((curr=>curr>2))) // the first element that is bigger than 2 is 3
arr.unshift(9)
L(arr) // [9,1,2,3,4]
L(arr.toString()) // '9,1,2,3,4'
L(arr.join())
let arr1=arr.splice(1,4)
L(arr) // [9]
L(arr1) // [1,2,3,4] the element deleted
arr1.reverse()
L(arr1) // [4,3,2,1]
arr1.splice(2,0,10)
L(arr1) // [4,3,10,2,1]
arr1.sort((a,b)=>{
return a-b
})
L(arr1) // [1,2,3,4,10]
L(arr1.at(-1)) // 10