异步和Promise

178 阅读3分钟

一.异步和回调

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()方法: