异步与Promise

85 阅读3分钟

1. 发请求和得到响应的时间范围

在JS里面,发一个网络请求,再成功得到响应,大概就是几百毫秒到1,2秒之间。

2. 回调

写了却不调用,给别人调用的函数,就是回调

//举例:
function f1() {}
function f2(fn) {
    fn()
}
f2(f1)// f2是我自己调用的,所以f2不是回调,f1是我写给f2调用的函数

3. 异步函数

function play() {
    setTimeout(()=>{
        return parseInt(Math.random() * 6) + 1
    },1000)
    //return undefined
}
//play()没有写return,那就是return undefined
//箭头函数里有return,返回真正的结果
//所以这是一个异步函数/异步任务
const n = play()
console.log(n) //undefined

4.异步和回调的关系

  • 关联

    异步任务需要在得到结果时通知 JS 来拿结果,怎么通知呢?

  1. 可以让 JS 留一个函数地址(电话号码)给浏览器
  2. 异步任务完成时浏览器调用该函数地址即可(拨打电话)
  3. 同时把结果作为参数传给该函数(电话里说可以来吃了)
  4. 这个函数是我写给浏览器调用的,所以是回调函数
  • 区别
  1. 异步任务需要用到回调函数来通知结果
  2. 但回调函数不一定只用在异步任务里
  3. 回调可以用到同步任务里
  4. array.forEach( n => console.log(n) ) 就是同步回调

5. 如何拿到异步结果

//可以用回调。写个函数,然后把函数地址给它
function f1(x) {console.log(x)}
play(f1)
//然后我要求play函数得到结果后把结果作为参数传给f1
function play(fn) {
    setTimeout(()=>{
        fn(parseInt(Math.random() * 6) + 1)
    },1000)
}

6. 面试题

const array = ['1', '2', '3'].map(parseInt)
console.log(array)
//等价于
const array2 = ['1','2','3'].map((item,i,arr)=>{
    return parseInt(item,i,arr)
    //parseInt('1',0,arr) =>1
    //parseInt('2',1,arr) =>NaN 1进制里面没有2
    //parseInt('3',2,arr) => NaN  2进制里面没有3
})
console.log(array2)

const array1 = ['1','2','3'].map((item,i,arr)=>{
    return parseInt(item)
})
console.log(array1)

const array3 = ['1','2','3'].map((item,i,arr)=>parseInt(item,i,arr));
console.log(array3)

image.png

7. 总结

异步任务不能拿到结果
于是我们传一个回调给异步任务
异步任务完成时调用回调
调用的时候把结果作为参数

8. 封装简易版ajax.js

ajax = (method,url,options) => {
    const {success,fail} = options //析构赋值
    const request = new XMLHttpRequest()
    request.open(method,url)
    request.onreadystatechange =()=>{
        if(request.readyState === 4) {
            //成功旧调用success,失败就调用fail
            if(request.status < 400) {
                success.call(null,request.response)
            } else if(request.status >= 400) {
                fail.call(null,request,request.status)
            }
        }
    }
    request.send()
}

ajax('get','/xxx',{
    success(response){},fail: (request,status)=>{}
}) //左边是 function 缩写,右边是箭头函数
//success:function(response)

9.封装简易版ajax.js改为promise.js

如何让一个回调的异步函数变成promise的异步函数:

第一步

  • return new Promise((resolve,reject)=>{...})
  • 任务成功则调用 resolve(result)
  • 任务失败则调用 reject(error)
  • resolve 和 reject 会再去调用成功和失败函数

第二步

  • 使用 .then(success, fail) 传入成功和失败函数
ajax = (method, url, options) => {
    return new Promise((resolve, reject) => {
        const {
            success,
            fail
        } = options //析构赋值
        const request = new XMLHttpRequest()
        request.open(method, url)
        request.onreadystatechange = () => {
            if (request.readyState === 4) {
                //成功就调用resolve,失败就调用reject
                if (request.status < 400) {
                    resolve.call(null, request.response)
                } else if (request.status >= 400) {
                    reject.call(null, request, request.status)
                }
            }
        }
        request.send()
    })
}

ajax('get', '/xxx').then((response) => {}, (request) => {})

10. 使用axios

axios.get('/5.json')
    .then(response=>
        console.log(response)
    )

参考资料:饥人谷