成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

自己動(dòng)手實(shí)現(xiàn)一個(gè)Promise

Yujiaao / 3283人閱讀

摘要:意味著操作成功完成。狀態(tài)的對(duì)象可能觸發(fā)狀態(tài)并傳遞一個(gè)值給相應(yīng)的狀態(tài)處理方法,也可能觸發(fā)失敗狀態(tài)并傳遞失敗信息。測(cè)試用例測(cè)試用例方法返回一個(gè)帶有拒絕原因參數(shù)的對(duì)象。

Promise基本用法

Promise 對(duì)象是一個(gè)代理對(duì)象,被代理的值在Promise對(duì)象創(chuàng)建時(shí)可能是未知的。

它允許你為異步操作的成功和失敗分別綁定相應(yīng)的處理方法(handlers)。 這讓異步方法可以像同步方法那樣返回值,但并不是立即返回最終執(zhí)行結(jié)果,而是一個(gè)能代表未來(lái)出現(xiàn)的結(jié)果的promise對(duì)象

一個(gè) Promise有以下幾種狀態(tài):

pending: 初始狀態(tài),既不是成功,也不是失敗狀態(tài)。
fulfilled: 意味著操作成功完成。
rejected: 意味著操作失敗。

pending 狀態(tài)的 Promise 對(duì)象可能觸發(fā)fulfilled 狀態(tài)并傳遞一個(gè)值給相應(yīng)的狀態(tài)處理方法,也可能觸發(fā)失敗狀態(tài)(rejected)并傳遞失敗信息。當(dāng)其中任一種情況出現(xiàn)時(shí),Promise 對(duì)象的 then 方法綁定的處理方法(handlers )就會(huì)被調(diào)用(then方法包含兩個(gè)參數(shù):onfulfilled 和 onrejected,它們都是 Function 類(lèi)型。當(dāng)Promise狀態(tài)為fulfilled時(shí),調(diào)用 then 的 onfulfilled 方法,當(dāng)Promise狀態(tài)為rejected時(shí),調(diào)用 then 的 onrejected 方法, 所以在異步操作的完成和綁定處理方法之間不存在競(jìng)爭(zhēng))。

因?yàn)?Promise.prototype.then 和 Promise.prototype.catch 方法返回promise 對(duì)象, 所以它們可以被鏈?zhǔn)秸{(diào)用。

var promise1 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    resolve("foo");
  }, 300);
});

promise1.then(function(value) {
  console.log(value);
  // expected output: "foo"
});

console.log(promise1);
// expected output: [object Promise]
Promise/A+

然后我們來(lái)了解一下Promise規(guī)范
Promises/A+規(guī)范(英文版)
Promises/A+規(guī)范(中文版)

Promise的實(shí)現(xiàn)

Promise是通過(guò)new創(chuàng)建的,可以通過(guò)構(gòu)造函數(shù)模式或者是ES6的class來(lái)實(shí)現(xiàn),這兒選擇構(gòu)造函數(shù)的方式來(lái)實(shí)現(xiàn)Promise,首先先完成一個(gè)簡(jiǎn)易版本的Promise。

function Promise(exector) {
    var _this = this
    this.status = "pending"
    this.value = undefined

    try {
      exector(resolve, reject)
    }catch(e) {
      reject(e)
    }

    function resolve(value) {
      if(_this.status === "pending") {
        _this.status = "fulfilled"
        _this.value = value
      }
    }

    function reject(value) {
      if(_this.status === "pending") {
        _this.status = "rejected"
        _this.value = value
      }
    }
  }

  Promise.prototype.then = function(resolveCallback, rejectCallback) {
    if(this.status === "fulfilled") {
      resolve(this.value)
    }

    if(this.status === "rejected") {
      reject(this.value)
    }
  }

  new Promise((resolve, reject)=> {
    resolve("1")
  }).then((data)=> {
    console.log("resolve" + data)
  }, (data)=> {
    console.log("reject" + data)
  }) //resolve1

  new Promise((resolve, reject)=> {
    setTimeout(()=> {
      resolve("1")
    }, 1000)
  }).then((data)=> {
    console.log("resolve" + data)
  }, (data)=> {
    console.log("reject" + data)
  }) //無(wú)法正常輸出

上面這個(gè)promise中resolve和reject在同步的情況下都能正常輸出,但是現(xiàn)在卻不支持異步,因?yàn)樵诋惒降臅r(shí)候調(diào)用then的時(shí)候狀態(tài)還是"pending",所以resolve/reject并不能如期執(zhí)行。

這個(gè)時(shí)候就需要一個(gè)存放后續(xù)調(diào)用事件的數(shù)組,當(dāng)異步函數(shù)執(zhí)行完畢后再執(zhí)行數(shù)組中的函數(shù)。

改進(jìn)后異步方法可以正常運(yùn)行:

function Promise(exector) {
    var _this = this
    this.status = "pending"
    this.value = undefined
    this.resolveList = []
    this.rejectList = []

    try {
      exector(resolve, reject)
    }catch(e) {
      reject(e)
    }

    function resolve(value) {
      if(_this.status === "pending") {
        _this.status = "fulfilled"
        _this.value = value
        _this.resolveList.forEach(item=> {
          item(_this.value)
          _this.resolveList.shift()
        })
      }
    }

    function reject(value) {
      if(_this.status === "pending") {
        _this.status = "rejected"
        _this.value = value
        _this.rejectList.forEach(item=> {
          item(_this.value)
          _this.rejectList.shift()
        })
      }
    }
  }

  Promise.prototype.then = function(resolveCallback, rejectCallback) {
    if(this.status === "fulfilled") {
      resolve(this.value)
    }

    if(this.status === "rejected") {
      reject(this.value)
    }

    if(this.status === "pending") {
      this.resolveList.push(resolveCallback)
      this.rejectList.push(rejectCallback)
    }
  }

  new Promise((resolve, reject)=> {
    setTimeout(()=> {
      resolve("1")
    }, 1000)
  }).then((data)=> {
    console.log("resolve" + data)
  }, (data)=> {
    console.log("reject" + data)
  })
鏈?zhǔn)秸{(diào)用

我們可以注意到Promise是可以鏈?zhǔn)秸{(diào)用的,這就需要then的方法返回一個(gè)Promise對(duì)象。

下面是一個(gè)鏈?zhǔn)秸{(diào)用的簡(jiǎn)單例子:

let promise = new Promise((resolve, reject)=> {
  resolve(666)
})

promise.then(data=> {
  console.log(data)
  return data + 1
}).then(data=> {
  console.log(data)
})
//666
//667

在Promise鏈中返回Promise:

let promise1 = new Promise((resolve, reject)=> {
  resolve(666)
})

let promise2 = new Promise((resolve, reject)=> {
  resolve(999)
})


promise1.then(data=> {
  console.log(data)

  return promise2
}).then(data=> {
  console.log(data)
})
//666
//999

關(guān)于這種寫(xiě)法需要注意的是,第二個(gè)完成處理程序被添加到第三個(gè)promise而不是return的promise2,上面的例子等價(jià)于:

let promise1 = new Promise((resolve, reject)=> {
  resolve(666)
})

let promise2 = new Promise((resolve, reject)=> {
  resolve(999)
})

let promise3 = promise1.then(data=> {
  console.log(data)

  return promise2
})

promise3.then(data=> {
  console.log(data)
})
//666
//999

當(dāng)異步的時(shí)候調(diào)用then函數(shù)的時(shí)候狀態(tài)為pending,這個(gè)時(shí)候同樣需要返回一個(gè)promise方便后續(xù)的鏈?zhǔn)秸{(diào)用。

所以修改為鏈?zhǔn)秸{(diào)用后的代碼為:

function Promise(exector) {
  var _this = this
  this.status = "pending"
  this.value = undefined
  this.resolveList = []
  this.rejectList = []

  try {
    exector(resolve, reject)
  }catch(e) {
    reject(e)
  }

  function resolve(value) {
    if(_this.status === "pending") {
      _this.status = "fulfilled"
      _this.value = value
      _this.resolveList.forEach(item=> {
        item(_this.value)
        _this.resolveList.shift()
      })
    }
  }

  function reject(value) {
    if(_this.status === "pending") {
      _this.status = "rejected"
      _this.value = value
      _this.rejectList.forEach(item=> {
        item(_this.value)
        _this.rejectList.shift()
      })
    }
  }
}

Promise.prototype.then = function(resolveCallback, rejectCallback) {
  var _this = this
  if(this.status === "fulfilled") {
    return new Promise((resolve, reject)=> {
      var result = resolveCallback(_this.value)
      if(result instanceof Promise) {
        result.then(resolve, reject)
      }else {
        resolve(result)
      }
    })
  }

  if(this.status === "rejected") {
    return new Promise((resolve, reject)=> {
      var result = rejectCallback(_this.value)
      if(result instanceof Promise) {
        result.then(resolve, reject)
      }else {
        reject(result)
      }
    })
  }

  if(this.status === "pending") {
    return new Promise((resolve, reject)=> {
      _this.resolveList.push(function() {
        var result = resolveCallback(_this.value)
        if(result instanceof Promise) {
          result.then(resolve, reject)
        }else {
          resolve(result)
        }
      })

      _this.rejectList.push(function() {
        var result = rejectCallback(_this.value)
        if(result instanceof Promise) {
          result.then(resolve, reject)
        }else {
          reject(result)
        }

      })

    })
  }
}


new Promise((resolve, reject)=> {
  resolve(666)
}).then((data)=> {
  console.log("resolve1:" + data)
  return 999
}).then((data)=> {
  console.log("resolve2:" + data)
})
//resolve1: 666
//resolve2: 999

new Promise((resolve, reject)=> {
  resolve(666)
}).then((data)=> {
  console.log("resolve1:" + data)
  return new Promise((resolve, reject)=> {
    resolve(999)
  })
}).then((data)=> {
  console.log("resolve2:" + data)
})
//resolve1: 666
//resolve2: 999

基本的功能已經(jīng)實(shí)現(xiàn),下面開(kāi)始實(shí)現(xiàn)Promise的all,race,resolve,reject方法,鏈?zhǔn)秸{(diào)用部分思路借鑒Promise/A+規(guī)范的實(shí)現(xiàn)

Promise.all()

該方法只接受一個(gè)有多個(gè)受監(jiān)聽(tīng)的Promise的可迭代對(duì)象(比如數(shù)組),只有當(dāng)可迭代對(duì)中所有Promise都被解決后才會(huì)返回resolve,如果參數(shù)中 promise 有一個(gè)失敗,此實(shí)例回調(diào)失?。╮eject),失敗原因的是第一個(gè)失敗 promise 的結(jié)果。

Promise.all = function(iterable) {
  return new Promise((resolve, reject) => {
    let result = []
    for(const item of iterable) {
      item.then(data => {
        result.push(data)
      }, reason=> {
        result = reason
        return
      })
    }

    resolve(result)
  })
}

//下面是測(cè)試用例
let p1 = new Promise((resolve, reject) => {
  resolve(666)
})

let p2 = new Promise((resolve, reject) => {
  resolve(888)
})

let p3 = new Promise((resolve, reject) => {
  resolve(999)
})

let p6 = new Promise((resolve, reject) => {
  reject(222)
})

let p4 = Promise.all([p1, p2, p3])

p4.then(data => {
  console.log(data)
})
//[666, 888, 999]
let p7 = Promise.all([p1, p3, p6])

p7.then(data => {
  console.log(data)
})
//222
Promise.race()

Promise.race(iterable) 方法返回一個(gè) promise,一旦迭代器中的某個(gè)promise解決或拒絕,返回的 promise就會(huì)解決或拒絕。

Promise.race = function(iterable) {
  return new Promise((resolve, reject) => {
    for(const item of iterable) {
      item.then(data => {
        resolve(data)
      }, reason=> {
        reject(reson)
      })
    }
  })
}
//測(cè)試用例
var p1 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 500, "one");
});

var p2 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, "two");
});

Promise.race([p1, p2]).then(function(value) {
  console.log(value);
  // Both resolve, but promise2 is faster
});
//two
Promise.resolve()
Promise.resolve = function(data) {
  return new Promise((resolve, reject) => {
    resolve(data)
  })
}

//測(cè)試用例
var p1 = Promise.resolve(123);

p1.then(function(value) {
  console.log(value);
});
//123
Promise.reject()

Promise.reject(reason)方法返回一個(gè)帶有拒絕原因reason參數(shù)的Promise對(duì)象。

Promise.resolve = function(data) {
  return new Promise((resolve, reject) => {
    reject(data)
  })
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108992.html

相關(guān)文章

  • 自己動(dòng)手,為vue寫(xiě)一個(gè)jsonp的方法

    摘要:它之后能夠被使用到很多場(chǎng)景中其他處理請(qǐng)求和響應(yīng)的方式,甚至任何需要生成自己的響應(yīng)的方式??偨Y(jié)到這里都講完了,其實(shí)沒(méi)什么難度,主要是自己項(xiàng)目中遇到了,但是中沒(méi)有這個(gè)方法啊。所以就想著實(shí)現(xiàn)了一個(gè),因?yàn)槠渌姆椒ㄒ捕挤庋b,不差這一個(gè)了。 Fetch 提供了對(duì)?Request?和?Response?(以及其他與網(wǎng)絡(luò)請(qǐng)求有關(guān)的)對(duì)象通用的定義。它之后能夠被使用到很多場(chǎng)景中:service wor...

    dongxiawu 評(píng)論0 收藏0
  • 動(dòng)手一個(gè)Promise

    摘要:一個(gè)后可以通過(guò)方法,指定和時(shí)的回調(diào)函數(shù)。構(gòu)造函數(shù)內(nèi)部要有一個(gè)值,用來(lái)保存上次執(zhí)行的結(jié)果值,如果報(bào)錯(cuò),則保存的是異常信息。因?yàn)槭且粋€(gè)構(gòu)造函數(shù),使用的寫(xiě)法,首先想到的就是有顯式聲明的。 showImg(https://segmentfault.com/img/bVbffEu?w=530&h=253); Javascript語(yǔ)言的執(zhí)行環(huán)境是單線(xiàn)程(single thread)。所謂單線(xiàn)程,就...

    shadajin 評(píng)論0 收藏0
  • 動(dòng)手一個(gè)Promise

    摘要:一個(gè)后可以通過(guò)方法,指定和時(shí)的回調(diào)函數(shù)。構(gòu)造函數(shù)內(nèi)部要有一個(gè)值,用來(lái)保存上次執(zhí)行的結(jié)果值,如果報(bào)錯(cuò),則保存的是異常信息。因?yàn)槭且粋€(gè)構(gòu)造函數(shù),使用的寫(xiě)法,首先想到的就是有顯式聲明的。 showImg(https://segmentfault.com/img/bVbffEu?w=530&h=253); Javascript語(yǔ)言的執(zhí)行環(huán)境是單線(xiàn)程(single thread)。所謂單線(xiàn)程,就...

    NervosNetwork 評(píng)論0 收藏0
  • 解析 Promise 原理,實(shí)現(xiàn)一個(gè)Promise

    摘要:解析原理,實(shí)現(xiàn)一個(gè)概述這篇文章旨在解析的異步實(shí)現(xiàn)原理,并且以中的為藍(lán)本實(shí)現(xiàn)一個(gè)簡(jiǎn)單的。具體的規(guī)范可以參見(jiàn)細(xì)節(jié)構(gòu)造器中必須傳入函數(shù),否則會(huì)拋出錯(cuò)誤。中的回調(diào)返回值會(huì)影響返回的對(duì)象。執(zhí)行器傳入構(gòu)造器的為函數(shù),并且在構(gòu)造時(shí)就會(huì)執(zhí)行。 解析 Promise 原理,實(shí)現(xiàn)一個(gè)Promise 概述 這篇文章旨在解析 Promise的異步實(shí)現(xiàn)原理,并且以 ES6中的 Promise 為藍(lán)本實(shí)現(xiàn)一個(gè)簡(jiǎn)單...

    silenceboy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<