回调和Promise

一、什么是回调

程序里面的任务可以根据执行顺序不同分为同步任务异步任务两种。

  • 同步任务是指那些没有被引擎挂起的,在主线程上排队执行的任务,只有前一个任务执行完毕,后一个任务才会执行,如:
function fn1(){
    console.log(1)
}
function fn2(){
    console.log(2)
}
fn1()//1
fn2()//2
  • 异步任务指被引擎挂起的、不在主线程上排队的任务,只有在满足某种条件后,引擎认为可以执行了,异步任务才会进入主线程,如:
function fn1(){
  setTimeout(function(){
        console.log(1)
    },1000)
}
function fn2(){
    console.log(2)
}
fn1()
fn2()//先打出2,再打出1

回调函数(callback)是异步操作最基本的方法,代表着当异步操作完成就调用被传入的函数。基本格式如下:

function fn1(callback){
    callback()
}//fn1是一个异步操作
function fn2(){
    console.log(2)
}
fn1(fn2)

二、什么是回调地狱

  • 回调函数容易理解和实现,但存在一个问题:回调地狱(callback hell)。
  • 回调地狱是指,当多个回调函数嵌套时,容易使得代码程序结构混乱、不容易被读懂,代码非常难看。如:
function fn1(){

}
fn1(function (){
    fn2(function (){
        fn3(function(){
            fn4()
        })
    })
})
  • 解决回调地狱的方法:
    1、给函数命名,减少函数嵌套,如:
function fn1(){

}
function fn2(){
    fn3()
}
function fn3(){
    fn4()
}
function fn4(){

}
fn1(fn2)

2、模块化
这里不展开讲。
3、用Promise

三、Promise

详细用法可参考阮一峰ES6的笔记

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise对象有以下两个特点:
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

基本的用法如下:
声明一个函数,返回一个Promise对象,成功就调用resolve(),失败则调用reject()
执行这个函数时,成功就调用.then(arg1,arg2)里的第一个函数arg1,失败则调用第二个函数arg2

function 获取用户信息(name){
    return new Promise(function(resolve,reject){
        if(name === '甲'){
            console.log('原来是小甲')
            resolve('甲')
        }else{
            console.log('谁啊不认识')
            reject('不认识')
        }
    })
}
function 打印信息(data){
    return new Promise(function(resolve,reject){
        console.log(data)
        resolve(data)
    })
}
function 获取好友信息(name){
    return new Promise(function(resolve,reject){
        if(name === '甲'){
            resolve('甲的好友有:张三、李四')
        }else{
            reject('不知道')
        }
    })
}
function 获取失败理由(reason){
        console.log('失败的理由是:'+reason)
        return Promise.reject('不认识')
}
function 修正前面的错误(){
    console.log('我搞不定了,求大神来帮忙')
}
获取用户信息('乙')
    .then(打印信息,获取失败理由)
    .then(获取好友信息,修正前面的错误)
    .then(打印信息)
    .catch(console.log('那就这样吧'))

四、async和await

要获取异步函数的结果时,可以采用await,如:

function 获取用户信息(name){
    return new Promise(function(resolve,reject){
        if(name === '甲'){
            console.log('原来是小甲')
            resolve('甲')
        }else{
            console.log('谁啊不认识')
            reject('不认识')
        }
    })
}
function 打印信息(data){
    return new Promise(function(resolve,reject){
        console.log(data)
        resolve(data)
    })
}
function 获取好友信息(name){
    return new Promise(function(resolve,reject){
        if(name === '甲'){
            resolve('甲的好友有:张三、李四')
        }else{
            reject('不知道')
        }
    })
}
function 获取失败理由(reason){
        console.log('失败的理由是: '+reason)
        return Promise.reject('不认识')
}
function 修正前面的错误(){
    console.log('我搞不定了,求大神来帮忙')
}
try{
    let 用户信息 = await 获取用户信息('乙')
    console.log(用户信息)
}catch(error){
    console.log('失败的理由是: '+error)
}

因为这是用同步的形式来写异步函数,浏览器无法识别是同步还是异步,所以在函数内部使用await时,在声明函数时要在声明前写async,否则会报错。

function buyFruit(){
    setTimeout(function(){
          console.log('apple')
    },5000)
}
function fn(){
    var result = await buyFruit()
    console.log(result)
}
fn()//Uncaught SyntaxError: await is only valid in async function

正确的写法是:

function buyFruit(){
    setTimeout(function(){
          console.log('apple')
    },5000)
}
async function fn(){
    var result = await buyFruit()
    console.log(result)
}
fn()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容