Table of Content

背景

Promise 主要的功能就是为了更好的解决异步编程问题.工作方式就是用于延迟代码执行并在未来执行当前这个作业.

一个Promise指定一些稍后要执行的代码,这个工作机制就和我jquery AJAX 中回调函数一样.明确标示作业代码是..否执行成功.以成功处理或失败处理为准.把promise串联在一起.

异步编程的背景

JS引擎建立在单线程事件循环的概念上,什么是单线程:单线程意味着同一时刻只能执行一段代码.这和其它语言比C++,JAVA,可以同时执行多段不同代码的多线程语言不一样.

多段代码可以同时访问或修改状态.但是维护很难.

JS引擎因为同一时刻只能执行一段代码.所以不用管另外的可能会运行的代码.js代码在执行中会把代码放置在作业队列中(job qeeue) ,在我们js代码中每一段准备被执行,就会被添加进作业队列.当结束当前代码执行后,就会进入下一个代码作业.这就是所谓的事件循环.是一个内部处理线程,可以监视代码执行并管理作业队列,因为是队伍.所以一定是依次进行.直到最后一个.

7.1 事件模型

当用户点击一个按扭或在键盘上按下一个健时.一个事件(event),比如onclick被触发.这个事件可能会对此交互进行响应,从而把一个新的代码作业添加到我当前的作业的队列尾部.这就是异步编程的最基本的形式.事件事处理程序代码一直到事件发生后才会被执行.比如:

let oBtn = document.getElementById('btn');
oBtn.onclick=function(){
    alert('中国')
}

以上代码,alert(中国) 直到oBtn点击之后才会执行.当被点击之后.赋值给onclick的匿名函数就被添加到了作业队列的尾部,并在队列前所有的任务结束之后再执行

7.2 回调模式

回调函数模式类似于事件模型.因为也会在后面一个时间点执行.不同的地方是回调是以参数的形式传入.

//下课后补全

$.ajax({
    url:'1.txt',
    success:function (res) {
         $.ajax({
             url:'1.txt',
             success:function(){
                 $.ajax({
                         url:'1.txt',
                         success:function(){
                             $.ajax({
                                     url:'1.txt',
                                     success:function(){
                                         $.ajax({
                                                 url:'1.txt',
                                                 success:function(){

                                                 }
                                             }
                                         )
                                     }
                                 }
                             )
                         }
                     }
                 )
             }
         }
    )
    }
})

7.3 Promise 基础

个人认为Promise是ES6,夜空中最亮的星.是为异步操作的结果所准备的占位符,可以用函数返回一个Promise,不需要事件或回调函数.比如:

//readFile函数会在某个时间点完成作业并赋值给promise
let promise = readFile('1.txt')

在这行代码中.我们可以理解为 readFile('1.txt') 并没有马上读取1.txt文件,可能会在稍后发生.这个函数会返回一个promise的对象以表示异步读取操作.可以在未来特定时间再来操作它,对结果进行操 作的时间.取决promise的生命周期是如何进行的;

7.4 Promise 的生命周期

有一个短暂的生命周期,初始为挂起,表示异步操作尚未结束,一个被挂起的promise,会被认为是未决的.在上面的一个例子中,promise会在readFile()返回它的时候就处于一个挂起状态.一旦异步操作结束,promise就会被认为是已决的.并进入两种可能的状态之一:

  1. 已完成:异步操作已成功结束
  2. 已拒绝:异步操作未成功结束,可能是一个错误,也可能是其它原因导致的.

相差词汇解释:

  1. pending:挂起,表示未结束的promise状态,相关专业词汇"挂起态".
  2. fulilled:已完成,表示已经成功结束的promise状态,可以理解为成功完成,相关专业词汇:"完成","被完成","完成态".
  3. rejected:已拒绝,表示已结束但失败的promise状态,相关词汇,"拒绝","被拒绝","拒绝态".
  4. unsettled:未决,未解决,表示promise尚未被完成或拒绝,与挂起是近义词.
  5. seteled:已决,已经解决,表示promise已经被完成或拒绝,注意这个与"已完成"或"已决议"不同,"已决的状态可能是,拒绝态(失败)
  6. resolve:决议,表示把promise推向成功态,,可以理解为决义通过,在promise概念中与完成是近义词.相关词汇"决义态",'已决议',"被决议".
  7. fulfillment handler: 完成处理函数,表示promise为完成态时会被调用的函数
  8. rejection handler:拒绝处理函数,表示promise为拒绝态时会被调用的的函数.

在promise内部有 一个promiseState属性会被设置为,"pending(挂起)","fulilled(已完成,)","rejected(已拒绝)",用来反应promise的当前状态.注意这属性并没有在promise对象中暴露出来.所以我们无法以编程的方式判断当前promise处理什么状态.但是可以使用 then() 方法 在promise的状态改变时执行一些操作.

then()方法在所有的promise上都存在.接受两个参数,第一个参数是被完成时要调用的函数,与异步操作关联的任何所有数据都会被传入这个函数.第二个参数是被拒绝时要调用的函数.和完成函数相似.拒绝函数也会被入与拒绝相关的数据.

传递给then()方法的两个参数都是可选的.比如:

let promise = new Promise((resolve,reject)=>{
    resolve('success')
    // reject()
});

console.log(promise)
promise
.then((res)=>{
    console.log(res)
},(err)=>{
    console.log(err)
})
.then(()=>{
    console.log('fdsfs')
})
.then(()=>{
    console.log('可以无限调用')
})
.catch(function(){
    console.log('这里是重大的错误')
})
// 这个方法的行为拒绝处理给then(),catch()和then()方用是等效的
promise.catch(function(err){
    console.log(err.message)
})

promise
.then(null,(err)=>{
    console.log(err)
})

就算是完成或是拒绝处理的函数在已经被解决之后添加到队列作业,还是被执行.允许你随时添加新的完成或拒绝处理函数.比如:

let promise = new Promise((resolve,reject)=>{
    resolve('success')
    // reject()
});

// 原始的完成处理
promise.then(function(res){
    console.log(res)
    // 添加另一个
    promise.then(function(res){
        console.log(res)

    })
})

以上代码中then()又为同一个promise添加了一另一个完成处理函数.这个promisen已经完成了.因此新的处理程序.就被加入到了任务队列中.在前面的执行完毕之后...再以同样的方式执行

调用 resolve() 触发了一个异步操作,在每次调用then()或catch()都会创建一个新的作业,会在promise已经决议时被执行.并且把它他们添加给了作业队列再执行:比如:

let promise = new Promise(function(resolve,reject){
    console.log('promise')
    resolve()   
});

promise.then(function(){
    console.log('resolved')
})

console.log('hello')

//结果:
promise
hello
resolved

尽管then()方法出现在hello之前.实际上会被稍后执行.和执行器中的console.log('promise')不同.完成处理函数和拒绝函数总是会在执行操作结束之后添加到作业队列的尾部.

基于Promise构造器行为的动态本质.是创建未决的最好的方式.如果想要一个promise代表一个已知的值.传值给resolve()函数并没有多大的意义.有两种方法可以指定值来创建已决的promise

  1. Promise.resolve()

接受一个参.返回一个完成状态.比如

let promise = Promise.resolve('hello')

promise.then(function(val){
    console.log(val)
})
  1. Promise.reject()

创建一个已拒绝的promise

let promise = Promise.reject('hello')
promise.catch(function(val){
    console.log(val)
})

7.5 AXIOS基于一个promise封装的一个ajax框架

Leave a Reply

Your email address will not be published.