异步和Promise

一.异步和回调

1.什么是异步?
如果可以直接拿到结果的是同步,而不能直接拿到结果的是异步(通过轮询或回调间接拿到结果)

2.什么是回调?
写给自己用的函数,不是回调;但是写给别人用的函数,是回调,即只管生不管养,举个例子
以AJAX为例,request.onreadystatechange就是写给浏览器调用的,再举个例子

function f1(){}
function f2(fn){
    fn()
}
f2(f1)   //f1是回调,因为没有调用f1,但是f1又给其他函数(f2)调用了

复制代码

3.异步和回调的关系?(合作关系,两者不是必然相互存在的)

关联:

  • 异步任务需要在得到结果是通知JS来拿结果
    复制代码
  • 怎么通知?让JS留一个函数地址给浏览器,异步任务完成时浏览器调用改函数地址即可,
    同时把结果作为参数传该函数,这个函数是写给浏览器调用的,所以是回调函数
    复制代码

区别:

  • 异步任务需要用到回调函数来通知结果
    复制代码
  • 但会调回函数不一定只用在异步任务里
    复制代码
  • 回调也可以用在同步任务里
    复制代码
  • array.forEach(n=>console.log(n))就是同步回调
    复制代码

举例子(摇骰子):
function f1(x){console.log(x)}
function f(fn){setTimeout(()=>{
fn(parseInt(Math.random()*6)+1);
},1000)}
f(f1)


function f1(x){console.log(x)}
f(f1)


改为:
f(x=>{console.log})

二.Promise的用法

两个结果的回调方法;
1.方法一:回调接受两个参数

fs.readFile('./1.txt',(error,data)=>{
    if(error){console.log('失败');return }
    console.log(data.toString())//成功
})
复制代码

2.方法二:搞两个回调

ajax('get',url,data=>{},error=>{})
ajax('get',url,{
    success:()=>{},fail:()=>{}
})

复制代码

使用Promise的原因(或者说,其他方法的缺点:):

一是不规范,没有成文的规定

二是回调地狱,代码变得很难看懂

三是很难进行错误处理

基于以上几个原因,promise出现了

ajax = (method,url,options)=>{
    const {sucess,fail} = options
    const request = new XMLHttpRequest()
    request.open(method,url)
    request.onreadystatechange = ()=>{
        if(request.readyState === 4){
            if(request.status < 400){
                sucess.call(null,request.response)
            }else if(request.status >= 400){
                fail.call(null,request,request.status)
            }
        }
    }
    request.send()
}


以上是把ajax封装了,以下是直接使用封装好的ajax:



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

以上代码改成promise

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.send()
   })
}
复制代码

记住了下面这句话:
return new Promise((resolve,reject)=>{})

三.手写Promise:

image.png

Promise有三种状态:Pending初始态,Fulfilled成功态,Rejected失败态。

手写一个Promise的代码如下:

function Promise(executor){
	let self = this;
  self.status = 'pending';//等待态
  self.value = undefined;//成功态
  self.value = undefined;//失败态
  
  function resolve(value){
  	if(self.status === 'pending'){
    	self.status = 'resolved';
      self.value = value;
    }
  }
  function reject(reason){
  	if(self.status === 'pending'){
    	self.status = 'rejected';
      self.reason = reason;
    }
  }
  try{
  	executor(resolve,reject);
  }catcch(e){
  	reject(e);//捕获时发生异常,直接失败。
  }
}

//onFufiled成功的回调
//onRejected 失败的回调
Promise.prototype.then = function(onFufiled,onRejected){
	let self = this;
  if(self.status === 'resolved'){
  	onFufiled(self.value);
  }
  if(self.status === 'rejected'){
  	onRejected(self.reason);
  }
}
module.exports = Promise;

复制代码

四.关于Promise的面试题:

Promise的几个方法,then,all,race,catch,finally,分别是什么意思:

then()方法:返回一个Promise,最多俩参数:Promise成功和失败情况的回调函数。

all()方法:

race()方法:
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享