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

資訊專欄INFORMATION COLUMN

JavaScript 異步數(shù)組

moven_j / 1430人閱讀

摘要:第二種則一定會(huì)執(zhí)行所有的異步函數(shù),即便你需要使用的是這些高階函數(shù)。并發(fā)實(shí)現(xiàn)的異步數(shù)組然后修改,使用即可上面的其他內(nèi)容終結(jié)整個(gè)鏈?zhǔn)讲僮鞑⒎祷亟Y(jié)果這里使用是為了兼容的調(diào)用方式調(diào)用方式不變。

JavaScript 異步數(shù)組
吾輩的博客原文: https://blog.rxliuli.com/p/5e...
場(chǎng)景
吾輩是一只在飛向太陽(yáng)的螢火蟲(chóng)

JavaScript 中的數(shù)組是一個(gè)相當(dāng)泛用性的數(shù)據(jù)結(jié)構(gòu),能當(dāng)數(shù)組,元組,隊(duì)列,棧進(jìn)行操作,更好的是 JavaScript 提供了很多原生的高階函數(shù),便于我們對(duì)數(shù)組整體操作。
然而,JavaScript 中的高階函數(shù)仍有缺陷 -- 異步!當(dāng)你把它們放在一起使用時(shí),就會(huì)感覺(jué)到這種問(wèn)題的所在。

例如現(xiàn)在,有一組 id,我們要根據(jù) id 獲取到遠(yuǎn)端服務(wù)器 id 對(duì)應(yīng)的值,然后將之打印出來(lái)。那么,我們要怎么做呢?

const wait = ms => new Promise(resolve => setTimeout(resolve, ms))

async function get(id) {
  // 這里只是為了模擬每個(gè)請(qǐng)求的時(shí)間可能是不定的
  await wait(Math.random() * id * 100)
  return "內(nèi)容: " + id.toString()
}

const ids = [1, 2, 3, 4]

你或許會(huì)下意識(shí)地寫(xiě)出下面的代碼

ids.forEach(async id => console.log(await get(id)))

事實(shí)上,控制臺(tái)輸出是無(wú)序的,而并非想象中的 1, 2, 3, 4 依次輸出

內(nèi)容: 2 ?????
內(nèi)容: 3 ?????
內(nèi)容: 1 ?????
內(nèi)容: 4

這是為什么呢?原因便是 JavaScript 中數(shù)組的高階函數(shù)并不會(huì)等待異步函數(shù)的返回!當(dāng)你在網(wǎng)絡(luò)上搜索時(shí),會(huì)發(fā)現(xiàn)很多人會(huì)說(shuō)可以使用 for-of, for-in 解決這個(gè)問(wèn)題。

;(async () => {
  for (let id of ids) {
    console.log(await get(id))
  }
})()

或者,使用 Promise.all 也是一種解決方案

;(async () => {
  ;(await Promise.all(ids.map(get))).forEach(v => console.log(v))
})()

然而,第一種方式相當(dāng)于丟棄了 Array 的所有高階函數(shù),再次重返遠(yuǎn)古 for 循環(huán)時(shí)代了。第二種則一定會(huì)執(zhí)行所有的異步函數(shù),即便你需要使用的是 find/findIndex/some/every 這些高階函數(shù)。那么,有沒(méi)有更好的解決方案呢?

思考

既然原生的 Array 不支持完善的異步操作,那么,為什么不由我們來(lái)實(shí)現(xiàn)一個(gè)呢?

實(shí)現(xiàn)思路:

創(chuàng)建異步數(shù)組類型 AsyncArray

內(nèi)置一個(gè)數(shù)組保存當(dāng)前異步操作數(shù)組的值

實(shí)現(xiàn)數(shù)組的高階函數(shù)并實(shí)現(xiàn)支持異步函數(shù)順序執(zhí)行

獲取到內(nèi)置的數(shù)組

class AsyncArray {
  constructor(...args) {
    this._arr = Array.from(args)
    this._task = []
  }
  async forEach(fn) {
    const arr = this._arr
    for (let i = 0, len = arr.length; i < len; i++) {
      await fn(arr[i], i, this)
    }
  }
}

new AsyncArray(...ids).forEach(async id => console.log(await get(id)))

打印結(jié)果確實(shí)有順序了,看似一切很美好?

然而,當(dāng)我們?cè)賹?shí)現(xiàn)一個(gè) map 試一下

class AsyncArray {
  constructor(...args) {
    this._arr = Array.from(args)
  }
  async forEach(fn) {
    const arr = this._arr
    for (let i = 0, len = arr.length; i < len; i++) {
      await fn(arr[i], i, this)
    }
  }
  async map(fn) {
    const arr = this._arr
    const res = []
    for (let i = 0, len = arr.length; i < len; i++) {
      res.push(await fn(arr[i], i, this))
    }
    return this
  }
}

調(diào)用一下

new AsyncArray(...ids).map(get).forEach(async res => console.log(res))
// 拋出錯(cuò)誤
// (intermediate value).map(...).forEach is not a function

然而會(huì)有問(wèn)題,實(shí)際上 map 返回的是 Promise,所以我們還必須使用 await 進(jìn)行等待

;(async () => {
  ;(await new AsyncArray(...ids).map(get)).forEach(async res =>
    console.log(res),
  )
})()

是不是感覺(jué)超級(jí)蠢?吾輩也是這樣認(rèn)為的!

鏈?zhǔn)秸{(diào)用加延遲執(zhí)行

我們可以嘗試使用鏈?zhǔn)秸{(diào)用加延遲執(zhí)行修改這個(gè) AsyncArray

/**
 * 保存高階函數(shù)傳入的異步操作
 */
class Action {
  constructor(type, args) {
    /**
     * @field 異步操作的類型
     * @type {string}
     */
    this.type = type
    /**
     * @field 異步操作的參數(shù)數(shù)組
     * @type {Function}
     */
    this.args = args
  }
}

/**
 * 所有的操作類型
 */
Action.Type = {
  forEach: "forEach",
  map: "map",
  filter: "filter",
}

/**
 * 真正實(shí)現(xiàn)的異步數(shù)組
 */
class InnerAsyncArray {
  constructor(arr) {
    this._arr = arr
  }
  async forEach(fn) {
    const arr = this._arr
    for (let i = 0, len = arr.length; i < len; i++) {
      await fn(arr[i], i, this)
    }
    this._arr = []
  }
  async map(fn) {
    const arr = this._arr
    const res = []
    for (let i = 0, len = arr.length; i < len; i++) {
      res.push(await fn(arr[i], i, this))
    }
    this._arr = res
    return this
  }
  async filter(fn) {
    const arr = this._arr
    const res = []
    for (let i = 0, len = arr.length; i < len; i++) {
      if (await fn(arr[i], i, this)) {
        res.push(arr[i])
      }
    }
    this._arr = res
    return this
  }
}

class AsyncArray {
  constructor(...args) {
    this._arr = Array.from(args)
    /**
     * @field 保存異步任務(wù)
     * @type {Action[]}
     */
    this._task = []
  }
  forEach(fn) {
    this._task.push(new Action(Action.Type.forEach, [fn]))
    return this
  }
  map(fn) {
    this._task.push(new Action(Action.Type.map, [fn]))
    return this
  }
  filter(fn) {
    this._task.push(new Action(Action.Type.filter, [fn]))
    return this
  }
  /**
   * 終結(jié)整個(gè)鏈?zhǔn)讲僮鞑⒎祷亟Y(jié)果
   */
  async value() {
    const arr = new InnerAsyncArray(this._arr)
    let result
    for (let task of this._task) {
      result = await arr[task.type](...task.args)
    }
    return result
  }
}

使用一下

new AsyncArray(...ids)
  .filter(async i => i % 2 === 0)
  .map(get)
  .forEach(async res => console.log(res))
  .value()

可以看到,確實(shí)符合預(yù)期了,然而每次都要調(diào)用 value(),終歸有些麻煩。

使用 then 以支持 await 自動(dòng)結(jié)束

這里使用 then() 替代它以使得可以使用 await 自動(dòng)計(jì)算結(jié)果

class AsyncArray {
  // 上面的其他內(nèi)容...
  /**
   * 終結(jié)整個(gè)鏈?zhǔn)讲僮鞑⒎祷亟Y(jié)果
   */
  async then(resolve) {
    const arr = new InnerAsyncArray(this._arr)
    let result
    for (let task of this._task) {
      result = await arr[task.type](...task.args)
    }
    // 這里使用 resolve(result) 是為了兼容 await 的調(diào)用方式
    resolve(result)
    return result
  }
}

現(xiàn)在,可以使用 await 結(jié)束這次鏈?zhǔn)秸{(diào)用了

await new AsyncArray(...ids).map(get).forEach(async res => console.log(res))

突然之間,我們發(fā)現(xiàn)了一個(gè)問(wèn)題,為什么會(huì)這么慢?一個(gè)個(gè)去進(jìn)行異步操作太慢了,難道就不能一次性全部發(fā)送出去,然后有序的處理結(jié)果就好了嘛?

并發(fā)異步操作

我們可以使用 Promise.all 并發(fā)執(zhí)行異步操作,然后對(duì)它們的結(jié)果進(jìn)行有序地處理。

/**
 * 并發(fā)實(shí)現(xiàn)的異步數(shù)組
 */
class InnerAsyncArrayParallel {
  constructor(arr) {
    this._arr = arr
  }
  async _all(fn) {
    return Promise.all(this._arr.map(fn))
  }
  async forEach(fn) {
    await this._all(fn)
    this._arr = []
  }
  async map(fn) {
    this._arr = await this._all(fn)
    return this
  }
  async filter(fn) {
    const arr = await this._all(fn)
    this._arr = this._arr.filter((v, i) => arr[i])
    return this
  }
}

然后修改 AsyncArray,使用 _AsyncArrayParallel 即可

class AsyncArray {
  // 上面的其他內(nèi)容...
  /**
   * 終結(jié)整個(gè)鏈?zhǔn)讲僮鞑⒎祷亟Y(jié)果
   */
  async then(resolve) {
    const arr = new InnerAsyncArrayParallel(this._arr)
    let result = this._arr
    for (let task of this._task) {
      result = await arr[task.type](...task.args)
    }
    // 這里使用 resolve(result) 是為了兼容 await 的調(diào)用方式
    if (resolve) {
      resolve(result)
    }
    return result
  }
}

調(diào)用方式不變。當(dāng)然,由于使用 Promise.all 實(shí)現(xiàn),也同樣受到它的限制 -- 異步操作實(shí)際上全部執(zhí)行了。

串行/并行相互轉(zhuǎn)換

現(xiàn)在我們的 _AsyncArray_AsyncArrayParallel 兩個(gè)類只能二選一,所以,我們需要添加兩個(gè)函數(shù)用于互相轉(zhuǎn)換。

class AsyncArray {
  constructor(...args) {
    this._arr = Array.from(args)
    /**
     * @field 保存異步任務(wù)
     * @type {AsyncArrayAction[]}
     */
    this._task = []
    /**
     * 是否并行化
     */
    this._parallel = false
  }
  // 其他內(nèi)容...

  parallel() {
    this._parallel = true
    return this
  }
  serial() {
    this._parallel = false
    return this
  }
  async then() {
    const arr = this._parallel
      ? new InnerAsyncArrayParallel(this._arr)
      : new InnerAsyncArray(this._arr)
    let result = this._arr
    for (let task of this._task) {
      result = await arr[task.type](...task.args)
    }
    if (resolve) {
      resolve(result)
    }
    return result
  }
}

現(xiàn)在,我們可以在真正執(zhí)行之前在任意位置對(duì)其進(jìn)行轉(zhuǎn)換了

await new AsyncArray(...ids)
  .parallel()
  .filter(async i => i % 2 === 0)
  .map(get)
  .forEach(async res => console.log(res))
并發(fā)執(zhí)行多個(gè)異步操作

然而,上面的代碼有一些隱藏的問(wèn)題

await 之后返回值不是一個(gè)數(shù)組

;(async () => {
  const asyncArray = new AsyncArray(...ids)
  console.log(await asyncArray.map(i => i * 2)) // InnerAsyncArray { _arr: [ 2, 4, 6, 8 ] }
})()

上面的 map, filter 調(diào)用在 await 之后仍會(huì)影響到下面的調(diào)用

;(async () => {
  const asyncArray = new AsyncArray(...ids)
  console.log(await asyncArray.map(i => i * 2)) // InnerAsyncArray { _arr: [ 2, 4, 6, 8 ] }
  console.log(await asyncArray) // InnerAsyncArray { _arr: [ 2, 4, 6, 8 ] }
})()

并發(fā)調(diào)用的順序不能確定,會(huì)影響到內(nèi)部數(shù)組,導(dǎo)致結(jié)果不能確定

;(async () => {
  const asyncArray = new AsyncArray(...ids)
  ;(async () => {
    console.log(
      await asyncArray.filter(async i => i % 2 === 1).map(async i => i * 2),
    ) // InnerAsyncArray { _arr: [ 2, 6 ] }
  })()
  ;(async () => {
    console.log(await asyncArray) // InnerAsyncArray { _arr: [ 2, 6 ] }
  })()
})()

先解決第一個(gè)問(wèn)題,這里只需要判斷一下是否為終結(jié)操作(forEach),是的話就直接返回結(jié)果,否則繼續(xù)下一次循環(huán)

class AsyncArray {
  // 其他內(nèi)容...

  async then(resolve, reject) {
    const arr = this._parallel
      ? new InnerAsyncArrayParallel(this._arr)
      : new InnerAsyncArray(this._arr)
    let result = this._arr
    for (let task of this._task) {
      const temp = await arr[task.type](...task.args)
      if (
        temp instanceof InnerAsyncArray ||
        temp instanceof InnerAsyncArrayParallel
      ) {
        result = temp._arr
      } else {
        // 如果已經(jīng)是終結(jié)操作就返回?cái)?shù)組的值
        if (resolve) {
          resolve(temp)
        }
        return temp
      }
    }
    if (resolve) {
      resolve(result)
    }
    return result
  }
}

現(xiàn)在,第一個(gè)問(wèn)題簡(jiǎn)單解決

;(async () => {
  const asyncArray = new AsyncArray(...ids)
  console.log(await asyncArray.map(i => i * 2)) // [ 2, 4, 6, 8 ]
})()

第二、第三個(gè)問(wèn)題看起來(lái)似乎是同一個(gè)問(wèn)題?其實(shí)我們可以按照常規(guī)思維解決第一個(gè)問(wèn)題。既然 await 之后仍然會(huì)影響到下面的調(diào)用,那就在 then 中把 _task 清空好了,修改 then 函數(shù)

class AsyncArray {
  // 其他內(nèi)容...

  async then(resolve, reject) {
    const arr = this._parallel
      ? new InnerAsyncArrayParallel(this._arr)
      : new InnerAsyncArray(this._arr)
    let result = this._arr
    for (let task of this._task) {
      const temp = await arr[task.type](...task.args)
      if (
        temp instanceof InnerAsyncArray ||
        temp instanceof InnerAsyncArrayParallel
      ) {
        result = temp._arr
      } else {
        // 如果已經(jīng)是終結(jié)操作就返回?cái)?shù)組的值
        if (resolve) {
          resolve(temp)
        }
        this._task = []
        return temp
      }
    }
    if (resolve) {
      resolve(result)
    }
    this._task = []
    return result
  }
}

現(xiàn)在,第一個(gè)問(wèn)題解決了,但第二個(gè)問(wèn)題不會(huì)解決。究其原因,還是異步事件隊(duì)列的問(wèn)題,雖然 async-await 能夠讓我們以同步的方式寫(xiě)異步的代碼,但千萬(wàn)不可忘記它們本質(zhì)上還是異步的!

;(async () => {
  await Promise.all([
    (async () => {
      console.log(
        await asyncArray.filter(async i => i % 2 === 1).map(async i => i * 2),
      ) // [ 2, 6 ]
    })(),
    (async () => {
      console.log(await asyncArray) // [ 2, 6 ]
    })(),
  ])
  console.log(await asyncArray) // [ 1, 2, 3, 4 ]
})()

可以看到,在使用 await 進(jìn)行等待之后就如同預(yù)期的 _task 被清空了。然而,并發(fā)執(zhí)行的沒(méi)有等待的 await asyncArray 卻有奇怪的問(wèn)題,因?yàn)樗窃?_task 清空之前執(zhí)行的。

并且,這帶來(lái)一個(gè)副作用: 無(wú)法緩存操作了

;(async () => {
  const asyncArray = new AsyncArray(...ids).map(i => i * 2)
  console.log(await asyncArray) // [ 2, 4, 6, 8 ]
  console.log(await asyncArray) // [ 1, 2, 3, 4 ]
})()
使用不可變數(shù)據(jù)

為了解決直接修改內(nèi)部數(shù)組造成的問(wèn)題,我們可以使用不可變數(shù)據(jù)解決這個(gè)問(wèn)題。試想:如果我們每次操作都返回一個(gè)新的 AsyncArray,他們之間沒(méi)有關(guān)聯(lián),這樣又如何呢?

class AsyncArray {
  constructor(...args) {
    this._arr = Array.from(args)
    /**
     * @field 保存異步任務(wù)
     * @type {Action[]}
     */
    this._task = []
    /**
     * 是否并行化
     */
    this._parallel = false
  }
  forEach(fn) {
    return this._addTask(Action.Type.forEach, [fn])
  }
  map(fn) {
    return this._addTask(Action.Type.map, [fn])
  }
  filter(fn) {
    return this._addTask(Action.Type.filter, [fn])
  }
  parallel() {
    this._parallel = true
    return this
  }
  serial() {
    this._parallel = false
    return this
  }
  _addTask(type, args) {
    const result = new AsyncArray(...this._arr)
    result._task = [...this._task, new Action(type, args)]
    result._parallel = this._parallel
    return result
  }
  /**
   * 終結(jié)整個(gè)鏈?zhǔn)讲僮鞑⒎祷亟Y(jié)果
   */
  async then(resolve, reject) {
    const arr = this._parallel
      ? new InnerAsyncArrayParallel(this._arr)
      : new InnerAsyncArray(this._arr)
    let result = this._arr
    for (let task of this._task) {
      const temp = await arr[task.type](...task.args)
      if (
        temp instanceof InnerAsyncArray ||
        temp instanceof InnerAsyncArrayParallel
      ) {
        result = temp._arr
      } else {
        // 如果已經(jīng)是終結(jié)操作就返回?cái)?shù)組的值
        if (resolve) {
          resolve(temp)
        }
        return temp
      }
    }
    if (resolve) {
      resolve(result)
    }
    return result
  }
}

再次測(cè)試上面的那第三個(gè)問(wèn)題,發(fā)現(xiàn)已經(jīng)一切正常了呢

并發(fā)調(diào)用的順序不能確定,但不會(huì)影響內(nèi)部數(shù)組了,結(jié)果是確定的

;(async () => {
  const asyncArray = new AsyncArray(...ids)
  await Promise.all([
    (async () => {
      console.log(
        await asyncArray.filter(async i => i % 2 === 1).map(async i => i * 2),
      ) // [ 2, 6 ]
    })(),
    (async () => {
      console.log(await asyncArray) // [ 1, 2, 3, 4 ]
    })(),
  ])
  console.log(await asyncArray) // [ 1, 2, 3, 4 ]
})()

操作可以被緩存

;(async () => {
  const asyncArray = new AsyncArray(...ids).map(i => i * 2)
  console.log(await asyncArray) // [ 2, 4, 6, 8 ]
  console.log(await asyncArray) // [ 2, 4, 6, 8 ]
})()
完整代碼

下面吾輩把完整的代碼貼出來(lái)

/**
 * 保存高階函數(shù)傳入的異步操作
 */
class Action {
  constructor(type, args) {
    /**
     * @field 異步操作的類型
     * @type {string}
     */
    this.type = type
    /**
     * @field 異步操作的參數(shù)數(shù)組
     * @type {Function}
     */
    this.args = args
  }
}

/**
 * 所有的操作類型
 */
Action.Type = {
  forEach: "forEach",
  map: "map",
  filter: "filter",
}

/**
 * 真正實(shí)現(xiàn)的異步數(shù)組
 */
class InnerAsyncArray {
  constructor(arr) {
    this._arr = arr
  }
  async forEach(fn) {
    const arr = this._arr
    for (let i = 0, len = arr.length; i < len; i++) {
      await fn(arr[i], i, this)
    }
    this._arr = []
  }
  async map(fn) {
    const arr = this._arr
    const res = []
    for (let i = 0, len = arr.length; i < len; i++) {
      res.push(await fn(arr[i], i, this))
    }
    this._arr = res
    return this
  }
  async filter(fn) {
    const arr = this._arr
    const res = []
    for (let i = 0, len = arr.length; i < len; i++) {
      if (await fn(arr[i], i, this)) {
        res.push(arr[i])
      }
    }
    this._arr = res
    return this
  }
}

class InnerAsyncArrayParallel {
  constructor(arr) {
    this._arr = arr
  }
  async _all(fn) {
    return Promise.all(this._arr.map(fn))
  }
  async forEach(fn) {
    await this._all(fn)
    this._arr = []
  }
  async map(fn) {
    this._arr = await this._all(fn)
    return this
  }
  async filter(fn) {
    const arr = await this._all(fn)
    this._arr = this._arr.filter((v, i) => arr[i])
    return this
  }
}

class AsyncArray {
  constructor(...args) {
    this._arr = Array.from(args)
    /**
     * @field 保存異步任務(wù)
     * @type {Action[]}
     */
    this._task = []
    /**
     * 是否并行化
     */
    this._parallel = false
  }
  forEach(fn) {
    return this._addTask(Action.Type.forEach, [fn])
  }
  map(fn) {
    return this._addTask(Action.Type.map, [fn])
  }
  filter(fn) {
    return this._addTask(Action.Type.filter, [fn])
  }
  parallel() {
    this._parallel = true
    return this
  }
  serial() {
    this._parallel = false
    return this
  }
  _addTask(type, args) {
    const result = new AsyncArray(...this._arr)
    result._task = [...this._task, new Action(type, args)]
    result._parallel = this._parallel
    return result
  }
  /**
   * 終結(jié)整個(gè)鏈?zhǔn)讲僮鞑⒎祷亟Y(jié)果
   */
  async then(resolve, reject) {
    const arr = this._parallel
      ? new InnerAsyncArrayParallel(this._arr)
      : new InnerAsyncArray(this._arr)
    let result = this._arr
    for (let task of this._task) {
      const temp = await arr[task.type](...task.args)
      if (
        temp instanceof InnerAsyncArray ||
        temp instanceof InnerAsyncArrayParallel
      ) {
        result = temp._arr
      } else {
        // 如果已經(jīng)是終結(jié)操作就返回?cái)?shù)組的值
        if (resolve) {
          resolve(temp)
        }
        return temp
      }
    }
    if (resolve) {
      resolve(result)
    }
    return result
  }
}
總結(jié)

那么,關(guān)于 JavaScript 中如何封裝一個(gè)可以使用異步操作高階函數(shù)的數(shù)組就先到這里了,完整的 JavaScript 異步數(shù)組請(qǐng)參考吾輩的 AsyncArray(使用 TypeScript 編寫(xiě))。

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

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

相關(guān)文章

  • javascript異步之Promise.all()、Promise.race()、Promise.

    摘要:的執(zhí)行與狀態(tài)無(wú)關(guān)當(dāng)?shù)玫綘顟B(tài)不論成功或失敗后就會(huì)執(zhí)行,原文鏈接參考鏈接對(duì)象 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步中的回調(diào)javascript異步與promisejavascript異步之Promise.resolve()、Promise.reject()javascript異步之Promise then和catchjavascript異步之a(chǎn)sync...

    clasnake 評(píng)論0 收藏0
  • 實(shí)現(xiàn) JavaScript 異步方法 Promise.all

    摘要:本次的任務(wù)假如。。。。。引擎發(fā)生了重大故障,方法變成了,為了拯救世界,需要開(kāi)發(fā)一個(gè)模塊來(lái)解決此問(wèn)題。實(shí)現(xiàn)首先要知道是什么是對(duì)異步編程的一種抽象。數(shù)組中任何一個(gè)為的話,則整個(gè)調(diào)用會(huì)立即終止,并返回一個(gè)的新的對(duì)象。 本次的任務(wù) 假如。。。。。 JavaScript v8 引擎發(fā)生了重大故障,Promise.all 方法變成了 undefined ,為了拯救 JavaScript 世界,需要...

    mushang 評(píng)論0 收藏0
  • javascript中實(shí)現(xiàn)異步+遍歷

    摘要:年月日更新后來(lái)在編程過(guò)程中發(fā)現(xiàn)用會(huì)更加方便。如果是沒(méi)辦法應(yīng)對(duì)異步。重新調(diào)了一下,發(fā)現(xiàn)幾點(diǎn)寫(xiě)下來(lái)異步操作這里的回調(diào)函數(shù)一定要寫(xiě)成這樣的形式,如果使用的是這樣的形式會(huì)指向這個(gè)匿名函數(shù)。 2017年7月20日更新 后來(lái)在編程過(guò)程中發(fā)現(xiàn)用iterator會(huì)更加方便。在Array的iteration方法里面有這么一個(gè):Array.prototype[@@iterator]()。用法是`arr[S...

    dreambei 評(píng)論0 收藏0
  • JavaScript Promises 初體驗(yàn)

    摘要:回調(diào)函數(shù)是的一大特色官方的基本都是以會(huì)回調(diào)方式傳遞函數(shù)返回值。針對(duì)這種普遍問(wèn)題,應(yīng)勢(shì)而生基本用法創(chuàng)建做一些異步操作的事情,然后一切正常的構(gòu)造器接受一個(gè)函數(shù)作為參數(shù),它會(huì)傳遞給這個(gè)回調(diào)函數(shù)兩個(gè)變量和。 Promise 是什么? Promise 對(duì)象用來(lái)進(jìn)行延遲(deferred) 和 異步(asynchronous) 計(jì)算。 一個(gè) Promise 處于以下三種狀態(tài)之一: pend...

    Baoyuan 評(píng)論0 收藏0
  • 翻譯連載 | 第 10 章:異步的函數(shù)式(上)-《JavaScript輕量級(jí)函數(shù)式編程》 |《你不知

    摘要:這就是積極的函數(shù)式編程。上一章翻譯連載第章遞歸下輕量級(jí)函數(shù)式編程你不知道的姊妹篇原創(chuàng)新書(shū)移動(dòng)前端高效開(kāi)發(fā)實(shí)戰(zhàn)已在亞馬遜京東當(dāng)當(dāng)開(kāi)售。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個(gè)流淌著滬江血液的純粹工程:認(rèn)真,是 HTML 最堅(jiān)實(shí)的梁柱;分享,是 CSS 里最閃耀的一瞥;總...

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

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

0條評(píng)論

moven_j

|高級(jí)講師

TA的文章

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