簡述函數式編程與JS異步編程、手寫Promise

簡答題
1、
1.javascript爲何是單線程?javascript

與javascript的設計初衷有關,最先javascript是運行在瀏覽器中的腳本語言,目的是爲了實現頁面上的動態交互,實現頁面的核心是dom操做,因此決定了javascript是單線程,不然會出現線程同步的問題:
好比多個線程同時操做一個dom元素,這時瀏覽器不知道要以誰的操做爲準,形成代碼執行順序混亂
javascript是單線程也就意味着瀏覽器有多個任務的時候要排隊依次進行,一個一個完成,這種模式的優勢是比較安全。缺點是若是咱們遇到一個特別消耗時間的任務,那麼後面的任務就會一直等着這個任務的完成,這樣會形成頁面卡死的狀況,會形成阻塞。
javascript語言沒法處理大量的耗時任務,爲了解決這個問題,javascript講執行任務分紅了兩種模式:同步模式和異步模式

2.同步模式java

同步模式指的是咱們的javascript代碼要依次執行,後面的代碼要等待前一句代碼執行完成才能執行,排隊執行,javascript代碼大多數是以同步模式進行執行的

3.異步模式promise

異步模式指的是咱們的javascript代碼不會等待前面的代碼執行完畢纔開始執行。

咱們將執行的代碼放入到調用棧中執行,若是是同步的直接執行,若是是異步的則放入消息隊列中等待執行,等到全部的代碼執行完畢,咱們的event loop就上場了,它會監聽調用棧和消息隊列中的任務,當調用棧中全部的任務結束之後,它會從消息隊列中依次取出回調函數壓入到調用棧,開始執行,直到整個循環結束

4.Event Loop瀏覽器

主線程從消息隊列中讀取事件,這個過程是循環不斷的,因此整個的這種運行機制稱爲Event Loop(事件循環),Event Loop是javascript的執行機制

5.消息隊列安全

消息隊列是暫時存放異步任務的地方,咱們的異步代碼會存放到消息隊列中,等到同步代碼執行完畢之後,event loop會從消息隊列中依次取出異步任務放到調用棧中再次執行。

6.宏任務,微任務dom

宏任務:當前調用棧中執行的代碼成爲宏任務,包括 主代碼快 ,定時器
微任務:宏任務執行完,在下一個宏任務開始以前須要執行的任務,能夠理解爲回調函數

運行機制:

在執行棧中執行一個宏任務
執行過程當中遇到微任務,將微任務添加到消息隊列中
當前宏任務執行完畢,當即執行微任務隊列中的任務
微任務執行完畢後,把下一個宏任務放到消息隊列中,經過eventloop放到調用棧中執行。

代碼題
1、異步

new Promise((resolve, reject) => {
  var a = 'hello'
  resolve(a)
}).then(value=> {
  var b = 'lagou'
  return value + b
}).then(value=> {
  var c = 'I❤U'
  console.log(value + c )
})

2、函數

練習1:
let isLastInStock = function(cars) {
    //獲取最後一條數據
    let last = cars => cars.pop()
    //獲取最後一條數據in_stock屬性值
    let getValue = last => last.in_stock
    return fp.flowRight(value, last)
}

練習2:
  let isFirstName = function(cars) {
    //獲取第一條數據
    //獲取第一條數據name屬性值
     return fp.flowRight(fp.prop('name'), fp.first)
}

練習3:
let _average = xs => {
      return fp.reduce(fp.add, 0, xs)
}
let averageDollarValue = cars => {
  return _average(fp.flowRight(fp.map(fp.prop('dollar_value')))(cars))
}

練習4:
let _underscore = fp.replace(/\s+/g, '_')
let arr = fp.flowRight(fp.map(fp.prop('name')))(cars)
let sanitizeNames = arr => {
  return fp.flowRight(fp.map(fp.flowRight(_underscore, fp.toLower)))(arr)
}

3、oop

//support.js
class Container {
      static of(value) {
        return new Container(value)
      }
      construtor(value) {
        this._value = value
      }
      map(fn) {
        return Container.of(fn(this._value))
      }
}

class MayBe {
      static of (value) {
        return new MayBe(value)
      }

     constructor (value) {
        this._value = value
      }

      map (fn) {
        return this.isNothing() ? MayBe.of(null) : MayBe.of(fn(this._value))
      }

      isNothing () {
        return this._value === null || this._value === undefined
      }
}

module.exports = { MayBe, Container }

練習1:
const fp = require('lodash/fp')
const { MayBe, Container } = require('./support')

let maybe= MayBe.of([5,6,1])
let ex1 = () => {
  return maybe.map(arr => fp.flowRight(fp.map(fp.add(1)))(arr))
}

練習2:
let ex2 = () => {
    return xs.map(arr => fp.first(arr))
}

練習3:
let ex3 = () => {
    return safeProp('name', user).map(x => fp.first(x))
}

練習4:
let ex4 = (n) => {
    return MayBe.of(n).map(n => parseInt(n))
}

4、ui

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class Promise {
      constructor(executor) {
    //狀態初始化爲pending
    this.status = PENDING
    //成功傳參
    this.value = undefined
    //失敗緣由
    this.reason = undefined
    //存儲成功的回調函數
    this.successCallbacks = []
    //存儲失敗的回調函數
    this.failCallbacks = []
    //成功
    let resolve = (value) => {
          if(this.status == PENDING) {
            this.status = FULFILLED
               this.value = value
            while (this.successCallbacks.length) this.successCallbacks.shift()()
          }
    }
    //失敗
    let reject = (reason) =>{
          if(this.status == PENDING) {
                this.status = REJECTED
             this.reason = reason
             while (this.failCallbacks.length)  this.failCallbacks.shift()()
          }
    }
    try {
          executor(resolve, reject)
    } catch(err) {
          reject(err)
    }
  }

  then(successCallback, failCallback) {
    //參數可有能夠無
    successCallback = successCallback ? successCallback : value => value
    failCallback = failCallback ? failCallback : reason => { throw reason}
    let promise2 = new Promise((resolve, reject)=>{
          if(this.status == FULFILLED) {
            setTimeout(()=>{ //異步讓promise2先建立
                  try {
                    let x = successCallback(this.value)
                    // 判斷 x的值是普通值仍是Promise對象
                    // 普通值 直接調用reslove
                    // 如果Promise對象,查看Promise對象返回的接口
                    // 再根據結果,決定調用resolve仍是reject
                    resolvePromise(promise2, x, resolve, reject)
                 } catch(err) {
                    reject(err)
                  }
               }, 0)


          } else if(this.status == REJECTED) {
            setTimeout(()=>{ //異步讓promise2先建立
                  try {
                    let x = failCallback(this.reason)
                    // 判斷 x的值是普通值仍是Promise對象
                    // 普通值 直接調用reslove
                    // 如果Promise對象,查看Promise對象返回的接口
                    // 再根據結果,決定調用resolve仍是reject
                    resolvePromise(promise2, x, resolve, reject)
                 } catch(err) {
                        reject(err)
                  }

               }, 0)
          } else {
            //存儲成功的回調函數
            this.successCallbacks.push(()=> {
                  setTimeout(()=>{ //異步讓promise2先建立
                        try {
                          let x = successCallback(this.value)
                          // 判斷 x的值是普通值仍是Promise對象
                          // 普通值 直接調用reslove
                          // 如果Promise對象,查看Promise對象返回的接口
                          // 再根據結果,決定調用resolve仍是reject
                          resolvePromise(promise2, x, resolve, reject)
                       } catch(err) {
                          reject(err)
                    }
             }, 0)
        })
        //存儲失敗的回調函數
    this.failCallbacks.push(()=> {
      setTimeout(()=>{ //異步讓promise2先建立
        try {
          let x = failCallback(this.reason)
          // 判斷 x的值是普通值仍是Promise對象
          // 普通值 直接調用reslove
          // 如果Promise對象,查看Promise對象返回的接口
          // 再根據結果,決定調用resolve仍是reject
          resolvePromise(promise2, x, resolve, reject)
       } catch(err) {
          reject(err)
        }

     }, 0)
    })
  }
})
   return promise2
  }

  finally (callback) {
    return this.then(value => {
          return MyPromise.resolve(callback()).then(() => value);
    }, reason => {
          return MyPromise.resolve(callback()).then(() => { throw reason })
    })
  }

  catch (failCallback) {
    return this.then(undefined, failCallback)
  }

  static all (array) {
let result = [];
let index = 0;
return new MyPromise((resolve, reject) => {
  function addData (key, value) {
    result[key] = value;
    index++;
    if (index === array.length) {
      resolve(result);
    }
  }
  for (let i = 0; i < array.length; i++) {
    let current = array[i];
    if (current instanceof MyPromise) {
      // promise 對象
      current.then(value => addData(i, value), reason => reject(reason))
    }else {
      // 普通值
      addData(i, array[i]);
    }
  }
})
  }

  static resolve (value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value));
       }
}

function resolvePromise (promise2, x, resolve, reject) {
      if(promise2 === x) {
        return reject(new TypeError('返回了相同的Promise對象'))
      }
      if(x instanceof Promise) {
        //promise對象
        x.then(resolve, reject)
      } else {
    //普通值
    resolve(x)
  }
}
module.exports = Promise
相關文章
相關標籤/搜索