国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

動手搞一個Promise

NervosNetwork / 3352人閱讀

摘要:一個后可以通過方法,指定和時的回調函數。構造函數內部要有一個值,用來保存上次執行的結果值,如果報錯,則保存的是異常信息。因為是一個構造函數,使用的寫法,首先想到的就是有顯式聲明的。

Javascript語言的執行環境是"單線程"(single thread)。所謂"單線程",就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務,以此類推。

這種模式的好處是實現起來比較簡單,執行環境相對單純;壞處是只要有一個任務耗時很長,后面的任務都必須排隊等著,會拖延整個程序的執行。常見的瀏覽器無響應(假死),往往就是因為某一段Javascript代碼長時間運行(比如死循環),導致整個頁面卡在這個地方,其他任務無法執行。

為了解決這個問題,Javascript語言將任務的執行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。

異步模式"編程的4種方法:回調函數、事件監聽、發布/訂閱、Promises對象
還有generator、async/await.

本文嘗試說一下對Promise的理解及如何實現。
1.Promise原理

promise對象有三種狀態,pending、fulfilled和rejected。promise對象內部保存一個需要執行一段時間的異步操作,當異步操作執行結束后可以調用resolve或reject方法,來改變promise對象的狀態,狀態一旦改變就不能再變。new一個promise后可以通過then方法,指定resolved和rejected時的回調函數。下面是我們日常使用Promise的代碼邏輯。
let p = new Promise((resolve,reject)=>{

    $.ajax({
    url: "../www/data.txt",
    dataType: "json",
    success(data){
        resolve(data);
     },
    error(err){
        reject(err);
     }
   }); 
});
p.then(function(data){
    alert("success"+data);
},function(err){
    alert("failed");
})

結合Promise A+規范,我們就可以分析一下我們要實現一個什么東西:

實現一個狀態機,有三個狀態,pending、fulfilled、rejected,狀態之間的轉化只能是pending->fulfilled、pending->rejected,狀態變化不可逆。
實現一個then方法,可以用來設置成功和失敗的回調
then方法要能被調用多次,所以then方法需要每次返回一個新的promise對象,這樣才能支持鏈式調用。
構造函數內部要有一個value值,用來保存上次執行的結果值,如果報錯,則保存的是異常信息。
2.實現原理

2.1實現狀態機

那我們現在就按照上面提到的原理和規范來實現這個Promise構造函數。
class myPromise {

    constructor(executor) {
        this.status = PENDING;
        this.value = "";
        this.Resolve = this.resolve.bind(this);
        this.Reject = this.reject.bind(this);
        this.then= this.then.bind(this);
        executor(this.Resolve, this.Reject);
    }

    resolve(value) {
        if (this.status === PENDING) {
            this.value = value;
            this.status = FULFILLED;
        }
    }

    reject(value) {
        if (this.status === PENDING) {
            this.value = value;
            this.status = REJECTED;
        }
    }

    then(onfulfilled, onrejected) {
        if (this.status === FULFILLED) {
            onfulfilled(this.value);
        }
        if (this.status === REJECTED) {
            onrejected(this.value);
        }
    }
}

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

const test = new myPromise((resolve, reject) => {
    resolve(100);
});
test.then((data) => {
    console.log(data);
}, (data) => {
});

因為Promise是一個構造函數,使用ES6的寫法,首先想到的就是有顯式constructor聲明的class。上面就是我們用class的實現,可以看到這樣我們就實現了這個狀態機,有status, value兩個屬性和resolve, reject, then三個函數;同時它有pending, fulfilled和rejected三個狀態,其中pending就可以切換為fulfilled或者rejected兩種。

運行一下,輸出了100,但是現在其實不是一個異步處理方案,代碼先運行了resolve(100)然后又運行了then函數,其實對于異步的情況沒有處理,不信的話就給resolve加一個setTimeout,好了,代碼又沒有輸出了。

2.2 實現異步設置狀態

作為一個異步處理的函數,在使用的時候,我們肯定是會先設置好不同異步返回后的處理邏輯(即then的成功、失敗調用函數),然后安心等待異步執行,最后再異步結束后,系統會自動根據我們的邏輯選擇調用不同回調函數。換句話說,then函數要對status為pending的狀態進行處理。處理的原理是設置兩個數組,在pending狀態下分別保存成功和失敗回調函數,當狀態改變后,再根據狀態去調用數組中保存的回調函數。

class myPromise {
constructor (executor) {

this.status = PENDING;
this.value = "";
this.onfulfilledArr = [];
this.onrejectedArr = [];
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
this.then = this.then.bind(this);
executor(this.resolve, this.reject);

}

resolve (value) {

if (this.status === PENDING) {
  this.value = value;
  this.onfulfilledArr.forEach(item => {
    item(this.value);
  })
  this.status = FULFILLED; 
}

}

reject (value) {

if (this.status === PENDING) {
  this.value = value;
  this.onrejectedArr.forEach(item => {
    item(this.value);
  })
  this.status = REJECTED;
}

}

then (onfulfilled, onrejected) {

if (this.status === FULFILLED) {
  onfulfilled(this.value);
}
if (this.status === REJECTED) {
  onrejected(this.value);
}
if (this.status === PENDING) {
  this.onfulfilledArr.push(onfulfilled);
  this.onrejectedArr.push(onrejected);
}

}
}

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

const test = new myPromise((resolve, reject) => {
setTimeout(() => {

resolve(100);

}, 2000)
});
test.then((data) => {
console.log(data);
},(data) => {});
可以這樣理解

new myPromise 有異步代碼

setTimeout(() => {
??? resolve(100);
}, 2000)

js是單線程的,這個時候會先把這個任務添加到定時觸發器線程中去(計時完畢后添加到事件隊列中,等待js引擎空閑后執行),先去執行下面的同步代碼
test.then((data) => {

??? console.log(data);

},(data) => {});
完成輸出及狀態改變。

但是Promise的一大特點就是可以鏈式調用,即test.then(success, fail).then(success, fail)...這就需要then返回一個新的Promise對象,而我們的程序現在明顯的是不支持的。那么繼續改一下。

2.3?實現鏈式調用

再觀察一下鏈式調用,如果成功和失敗的函數中有返回值,這個值要作為參數傳給下個then函數的成功或失敗回調。所以我們要在返回的new Promise中調用相應的函數。

class myPromise {
constructor (executor) {

this.status = PENDING;
this.value = "";
this.onfulfilledArr = [];
this.onrejectedArr = [];
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
this.then = this.then.bind(this);
executor(this.resolve, this.reject);

}

resolve (value) {

if (this.status === PENDING) {
  this.value = value;
  this.onfulfilledArr.forEach(item => {
    item(this.value);
  })
  this.status = FULFILLED; 
}

}

reject (value) {

if (this.status === PENDING) {
  this.value = value;
  this.onrejectedArr.forEach(item => {
    item(this.value);
  })
  this.status = REJECTED;
}

}

then (onfulfilled, onrejected) {

if (this.status === FULFILLED) {
  const res = onfulfilled(this.value);
  return new Promise(function(resolve, reject) {
    resolve(res);
  })
}
if (this.status === REJECTED) {
  const res = onrejected(this.value);
  return new Promise(function(resolve, reject) {
    reject(res);
  })
}
if (this.status === PENDING) {
  const self = this;
  return new Promise(function(resolve, reject) {
    self.onfulfilledArr.push(() => {
      const res = onfulfilled(self.value)
      resolve(res);
    });
    self.onrejectedArr.push(() => {
      const res = onrejected(self.value)
      reject(res);
    });
  })
}

}
}

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

const test = new myPromise((resolve, reject) => {
setTimeout(() => {

resolve(100);

}, 2000)
});
test.then((data) => {
console.log(data);
return data + 5;
},(data) => {})
.then((data) => {
console.log(data)
},(data) => {});

再運行一下,輸出100,105。好了,一個簡單的Promise就實現好了。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/52860.html

相關文章

  • 動手一個Promise

    摘要:一個后可以通過方法,指定和時的回調函數。構造函數內部要有一個值,用來保存上次執行的結果值,如果報錯,則保存的是異常信息。因為是一個構造函數,使用的寫法,首先想到的就是有顯式聲明的。 showImg(https://segmentfault.com/img/bVbffEu?w=530&h=253); Javascript語言的執行環境是單線程(single thread)。所謂單線程,就...

    shadajin 評論0 收藏0
  • 自己動手實現一個Promise

    摘要:意味著操作成功完成。狀態的對象可能觸發狀態并傳遞一個值給相應的狀態處理方法,也可能觸發失敗狀態并傳遞失敗信息。測試用例測試用例方法返回一個帶有拒絕原因參數的對象。 Promise基本用法 Promise 對象是一個代理對象,被代理的值在Promise對象創建時可能是未知的。 它允許你為異步操作的成功和失敗分別綁定相應的處理方法(handlers)。 這讓異步方法可以像同步方法那樣返回值...

    Yujiaao 評論0 收藏0
  • 自己動手,為vue寫一個jsonp的方法

    摘要:它之后能夠被使用到很多場景中其他處理請求和響應的方式,甚至任何需要生成自己的響應的方式。總結到這里都講完了,其實沒什么難度,主要是自己項目中遇到了,但是中沒有這個方法啊。所以就想著實現了一個,因為其他的方法也都封裝,不差這一個了。 Fetch 提供了對?Request?和?Response?(以及其他與網絡請求有關的)對象通用的定義。它之后能夠被使用到很多場景中:service wor...

    dongxiawu 評論0 收藏0
  • JavaScript基礎——深入學習async/await

    摘要:等待的基本語法該關鍵字的的意思就是讓編譯器等待并返回結果。這里并不會占用資源,因為引擎可以同時執行其他任務其他腳本或處理事件。接下來,我們寫一個火箭發射場景的小例子不是真的發射火箭 本文由云+社區發表 本篇文章,小編將和大家一起學習異步編程的未來——async/await,它會打破你對上篇文章Promise的認知,竟然異步代碼還能這么寫! 但是別太得意,你需要深入理解Promise后,...

    張金寶 評論0 收藏0

發表評論

0條評論

NervosNetwork

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<