> 文章列表 > 网络请求实战-实战Fetch和Promise相关的架构

网络请求实战-实战Fetch和Promise相关的架构

网络请求实战-实战Fetch和Promise相关的架构

目录

Promise神器(承诺)

Promise+Coding示例

Promise常见用法

简单的promise

Fetch的基本用法

fetch

Fetch基本用法

Fetch+Promise场景举例

小结


Promise神器(承诺)

Promise+Coding示例

  • 代表异步求值的过程结果

 promise链式调用,可以一直promise下去

// example 01
const promise = new Promise((resolve, reject) => {resolve(100)
}).then(data => {console.log(data)
})
// 100
// example 02
const promise = new Promise((resolve, reject) => {resolve(100)
}).then(data => {console.log(data)return 'abc' // 直接返回一个值
})
.then(data => { // 此处不用执行promise了,直接fulfilled了一个'abcconsole.log(data)
})
// 100 abc
// example 03
function wait(ms = 1000, data) {return new Promise((resolve) => {setTimeout(() => {resolve(data)}, ms)})
}
const promise = new Promise((resolve, reject) => {resolve(100)
}).then(data => {console.log(data) // 100return wait(1000, 'abc') // 等待1s,返'abc'
})
.then(data => {console.log(data) // 等待1000ms,打印'abc'
})
// example04
const promise = new Promise((resolve, reject) => {reject("some error")
}).then(data => {console.log("1", data) // 不执行
}).catch(ex => {console.error(ex) // some errorreturn "GO"
}).then(data => {console.log(data) // GO
})
// example05
function wait(ms = 1000, data){return new Promise((resolve, reject) => {setTimeout(() => {resolve(data)}, ms)})
}
async function foo(){console.log('--begin--')const one = await wait(1000, 1) console.log('--tick 1--') // 等待一秒 const two = await wait(1000, 2)console.log('--tick 2--') // 再等待一秒 console.log(one, two) // 1, 2await Promise.reject('some error')try{await Promise.reject('some error')} catch(ex) {console.log(ex)  // some error}
}
foo()
// example 6
function wait(ms = 1000, data){return new Promise((resolve, reject) => {setTimeout(() => {resolve(data)}, ms)})
}
// 工厂方法
Promise.all([wait(200, 1), wait(100, 2)]).then(data => {console.log('all', data) // 等2个promise都结束,返回这个数组[1,2]})
Promise.race([wait(200, 1), wait(100, 2)]).then(data => {console.log('race', data) // race是在这个执行promise数组中返回第一个拿到的值})

Promise常见用法

  • resolve & reject
  • Chain (链执行)
  • 并发和竞争(all 和 race)
  • 异常处理 (try catch)

简单的promise

const PENDING = 1
const FULLFILLED = 2
const REJECTED = 3
class Promise{constructor(executor){this.state = PENDINGconst resolver = (value) => {if(this.state === PENDING) {this.state = FULLFILLED this.value = value }for(let [onFullFill, resolve] of this.fullfills) {const x = onFullFill(this.value)resolve(x)}}const rejector = () => {this.state = REJECTED}this.fullfills = []executor(resolver, rejector)}then(onFullfill) {return new Promise((resolve, rejector) => {switch(this.state) {case FULLFILLED:const x = onFullfill(this.value)resolve(x)breakcase PENDING:this.fullfills.push([onFullfill, resolve])break}})}
}
new Promise((resolve) => {setTimeout(() => {resolve('123')})
}).then(data => {console.log(data) // 123return '456' 
}).then(data => {console.log(data) // 456return data
})

Fetch的基本用法

fetch

一个让处理http pipeline更容易的工具(MDN)

  • 返回Promise
  • Resolve发生在网络通信正常(404,500也是resolve)
  • Reject发生在网络通信异常
  • 默认不接受cookie(需要设置)

存在队头阻塞,服务端负载充足

Fetch基本用法

  • GET/POST/PUT/DELETE
  • Headers
  • Cookie
  • 缓存
fetch("/product", {method: "POST",headers : {"Content-Type" : "application/json"    },body: JSON.stringify({ name: "123苹果" }),
}).then((resp) => console.log(resp.status))
fetch("/product", {method: "POST",headers : {"Content-Type" : "application/json"    },body: JSON.stringify({ name: "".padStart(100000, "A")}),
}).then((resp) => console.log(resp.status))
// node端 需要引用实例
const fetch = require('node-fetch')
const promise = fetch('https://www.baidu.com', {method: 'POST',headers: {'Content-Type': "application/json",    },credentials: 'include', // 设置之后可以接收服务端的Cookie
})
async function foo() {const resp = await fetch("http://www.baidu.com", {headers: {'user-agent': "Mozillia"       }   })const text = await resp.text()console.log(text)
}
foo()
// 缓存
fetch("https://www.baidu.com", {cache: 'force-cache'})

Fetch+Promise场景举例

1.指数补偿,专门应付移动端频繁网络波动的

按照指数的时间倍数重复发送请求

  • 0ms
  • 200ms
  • 400ms
  • 800ms
  • 1600ms
  • 3200ms
  • fail
// 示例程序
const fetch = require('node-fetch')
function request(url){let resolved = falselet t = 1 return new Promise((resolve) => {function doFetch(){if(resolved || t > 16) {return}fetch(url).then((resp) => {return resp.text()}).then(data => {if(!resolved) {resolved = trueresolve(data)console.log('t=', t)}}).catch(ex => {console.error(ex)})setTimeout(() => {doFetch()t *= 2}, t * 100)}doFetch()})
}
request('http://www.baidu.com').then(data => {console.log(data.length)})
setTimeout(() => {
}, 3000)
// 有缺陷,所有请求都发送了
function wait(ms, f) {return new Promise((resolve) => {setTimeout(()=> {resolve(f())        }, ms)    })
}
function request(url) {Promise.race([fetch(url),wait(100, ()=> fetch(url) ),wait(200, ()=> fetch(url) ),wait(400, ()=> fetch(url) ),wait(800, ()=> fetch(url) ),wait(1600, ()=> fetch(url) ),])
}
request('http://www.baidu.com').then(resp => {console.log(resp)})
setTimeout(() => {
}, 3000)

2.并发处理和时间窗口,底层前端请求优化的

多个资源并发请求(Promise.all)

基于时间窗口过滤重复请求

const fetch = require('node-fetch')
function hash(args) {return args.join(',')
}
function window_it(f, time = 50) {let w = {} let flag = false return (...args) => {// 参数传递return new Promise((resolve) => {if (!w[hash(args)]) {w[hash(args)] = {func: f,args,resolvers: [],}}if (!flag) {flag = truesetTimeout(() => {Object.keys(w).forEach((key) => {const { func, args, resolvers } = w[key]const promise = func(...args).then((resp) => resp.text()).then((text) =>resolvers.map((r) => {r(text)}))})flag = false}, time)}console.log(args)w[hash(args)].resolvers.push(resolve)})}
}
const request = window_it(fetch, 20)
request('http://www.baidu.com').then(txt => console.log(txt.length))
request('http://www.baidu.com').then(txt => console.log(txt.length))
request('http://www.baidu.com').then(txt => console.log(txt.length))
request('http://www.zhihu.com').then(txt => console.log(txt.length))
request('http://www.baidu.com').then(txt => console.log(txt.length))
request('http://www.baidu.com').then(txt => console.log(txt.length))

小结

  • 为什么不教Axios? 因为fetch是浏览器提供的标准
  • 优化问题要工程化处理(所有页面的优化,请求优化,页面大小优化,白屏的优化【需要用到算法,数据结构和相关的架构知识,是针对一类问题提供工具】)