成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

await在forEach中不起作用如何解決-創(chuàng)新互聯(lián)

這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)await在forEach中不起作用如何解決,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)、外貿(mào)營銷網(wǎng)站建設(shè)服務(wù)團(tuán)隊(duì)是一支充滿著熱情的團(tuán)隊(duì),執(zhí)著、敏銳、追求更好,是創(chuàng)新互聯(lián)的標(biāo)準(zhǔn)與要求,同時(shí)竭誠為客戶提供服務(wù)是我們的理念。創(chuàng)新互聯(lián)建站把每個(gè)網(wǎng)站當(dāng)做一個(gè)產(chǎn)品來開發(fā),精雕細(xì)琢,追求一名工匠心中的細(xì)致,我們更用心!

首先引一個(gè)很簡單題目:給一個(gè)數(shù)組,每隔1s打印出來.這里我把我一開始在項(xiàng)目中的代碼貼出來.(當(dāng)然這里完全和業(yè)務(wù)無關(guān)的)

const _ = require('lodash');
const echo = async (i) => {
  setTimeout(() => {
    console.log('i===>', i);
  }, 5000);
}
let arrs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const task = async () => {
  _.forEach(arrs, async (i) => {
    await echo(i);
  })
}
const run = async () => {
  console.log('run-start====>date:', new Date().toLocaleDateString())
  await task() ;
  console.log('run-end====>date:', new Date().toLocaleDateString())
}
(async () => {
  console.log('start...')
  await run();
  console.log('end...')
})()
// start...
// run-start====>date: 2018-8-25
// run-end====>date: 2018-8-25
// end...
// i===> 1
// i===> 2
// i===> 3
// i===> 4
// i===> 5
// i===> 6
// i===> 7
// i===> 8
// i===> 9

上面的代碼和輸出已經(jīng)給出了,很奇怪,這里的await并沒有其效果.一開始因?yàn)槭羌恿藰I(yè)務(wù),是我的業(yè)務(wù)代碼出了問題,然后我就把代碼抽出來了,還是不起作用,當(dāng)時(shí)我是真的對對await懷疑了。

最后還是給出問題的答案:

lodash的forEach和[].forEach不支持await,如果非要一邊遍歷一邊執(zhí)行await,可使用for-of

這里給出正確的代碼:

const _ = require('lodash');
const echo = async (i) => {
  return new Promise((resolve,reject)=>{
    setTimeout(() => {
      console.log('i===>', i,new Date().toLocaleTimeString());
      resolve(i) ;
    }, 2000);
  })
}
let arrs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const task = async () => {
  // _.forEach(arrs, async (i) => {
  //  await echo(ji) ;
  // })
  // arrs.forEach(async (i )=> {
  //   await echo(i) ;
  // });
  for (const i of arrs) {
    await echo(i) ;
  }
}
const run = async () => {
  console.log('run-start====>date:', new Date().toLocaleDateString())
  await task() ;
  console.log('run-end====>date:', new Date().toLocaleDateString())
}
(async () => {
  console.log('start...')
  await run();
  console.log('end...')
})()
// 輸出
start...
run-start====>date: 2018-8-26
i===> 1 20:51:29
i===> 2 20:51:31
i===> 3 20:51:33
i===> 4 20:51:35
i===> 5 20:51:37
i===> 6 20:51:39
i===> 7 20:51:42
i===> 8 20:51:44
i===> 9 20:51:46
i===> 10 20:51:48
run-end====>date: 2018-8-26
end...

三、總結(jié)

當(dāng)解決問題的時(shí)候,有時(shí)候可以使用排除法,比方說在這個(gè)例子中,我們知道await這個(gè)機(jī)制肯定是沒問題的,如果真的有問題肯定不會輪到我測出來,那么其實(shí)剩下來的問題只能是for遍歷的原因了.

因?yàn)槲乙婚_始是用lodash實(shí)現(xiàn)的,那么就可以想是不是lodash的forEach沒有作(或者做了多余)await處理,此時(shí)就可以換種方式試試了,總的來說還是經(jīng)驗(yàn)的問題吧。

補(bǔ)充:在 forEach 中使用 async/await 遇到的問題

一、問題描述

前幾天,項(xiàng)目中遇到一個(gè) JavaScript 異步問題:

有一組數(shù)據(jù),需要對每一個(gè)數(shù)據(jù)進(jìn)行一個(gè)異步處理,并且希望處理的時(shí)候是同步的。

用代碼描述如下:

// 生成數(shù)據(jù)
const getNumbers = () => {
 return Promise.resolve([1, 2, 3])
}
// 異步處理
const doMulti = num => {
 return new Promise((resolve, reject) => {
  setTimeout(() => {
   if (num) {
    resolve(num * num)
   } else {
    reject(new Error('num not specified'))
   }
  }, 2000)
 })
}
// 主函數(shù)
const main = async () => {
 console.log('start');
 const nums = [1, 2, 3];
 nums.forEach(async (x) => {
  const res = await doMulti(x);
  console.log(res);
 });
 console.log('end');
};
// 執(zhí)行
main();

在這個(gè)例子中,通過 forEach 遍歷地將每一個(gè)數(shù)字都執(zhí)行 doMulti 操作。代碼執(zhí)行的結(jié)果是:首先會立即打印 start、end 。2 秒后,一次性輸出 1,4,9。

這個(gè)結(jié)果和我們的預(yù)期有些區(qū)別,我們是希望每間隔 2 秒,執(zhí)行一次異步處理,依次輸出 1,4,9。所以當(dāng)前代碼應(yīng)該是并行執(zhí)行了,而我們期望的應(yīng)該是串行執(zhí)行。

我們嘗試把 forEach 循環(huán)替換成 for 循環(huán):

const main = async () => {
 console.log('start');
 const nums = await getNumbers();
 for (const x of nums) {
  const res = await doMulti(x);
  console.log(res);
 }
 console.log('end');
};

執(zhí)行結(jié)果完全符合了預(yù)期:依次輸出:start、1, 4, 9, end 。

二、問題分析

思路都是一樣的,只是使用的遍歷方式不一樣而已,為什么會出現(xiàn)這樣的情況呢?在 MDN 上查找了一下 forEach 的 polyfill 參考 MDN-Array.prototype.forEach() :

// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: /tupian/20230522/
if (!Array.prototype.forEach) {
 Array.prototype.forEach = function(callback, thisArg) {
  var T, k;
  if (this == null) {
   throw new TypeError(' this is null or not defined');
  }
  // 1. Let O be the result of calling toObject() passing the
  // |this| value as the argument.
  var O = Object(this);
  // 2. Let lenValue be the result of calling the Get() internal
  // method of O with the argument "length".
  // 3. Let len be toUint32(lenValue).
  var len = O.length >>> 0;
  // 4. If isCallable(callback) is false, throw a TypeError exception. 
  // See: http://es5.github.com/#x9.11
  if (typeof callback !== "function") {
   throw new TypeError(callback + ' is not a function');
  }
  // 5. If thisArg was supplied, let T be thisArg; else let
  // T be undefined.
  if (arguments.length > 1) {
   T = thisArg;
  }
  // 6. Let k be 0
  k = 0;
  // 7. Repeat, while k < len
  while (k < len) {
   var kValue;
   // a. Let Pk be ToString(k).
   //  This is implicit for LHS operands of the in operator
   // b. Let kPresent be the result of calling the HasProperty
   //  internal method of O with argument Pk.
   //  This step can be combined with c
   // c. If kPresent is true, then
   if (k in O) {
    // i. Let kValue be the result of calling the Get internal
    // method of O with argument Pk.
    kValue = O[k];
    // ii. Call the Call internal method of callback with T as
    // the this value and argument list containing kValue, k, and O.
    callback.call(T, kValue, k, O);
   }
   // d. Increase k by 1.
   k++;
  }
  // 8. return undefined
 };
}

從上面的 polyfill 中的 setp 7 ,我們可以簡單地理解成下面的步驟:

Array.prototype.forEach = function (callback) {
 // this represents our array
 for (let index = 0; index < this.length; index++) {
  // We call the callback for each entry
  callback(this[index], index, this);
 };
};

相當(dāng)于 for 循環(huán)執(zhí)行了這個(gè)異步函數(shù),所以是并行執(zhí)行,導(dǎo)致了一次性全部輸出結(jié)果:1,4,9 。

const main = async () => {
 console.log('start');
 const nums = await getNumbers();
 // nums.forEach(async (x) => {
 //  const res = await doMulti(x);
 //  console.log(res);
 // });
 for (let index = 0; index < nums.length; index++) {
  (async x => {
   const res = await doMulti(x)
   console.log(res)
  })(nums[index])
 }
 console.log('end');
};

三、解決方案

現(xiàn)在,我們把問題分析清楚了。前面用 for-of 循環(huán)來代替 forEach 作為解決方案 ,其實(shí)我們也可以改造一下 forEach :

const asyncForEach = async (array, callback) => {
 for (let index = 0; index < array.length; index++) {
  await callback(array[index], index, array);
 }
}
const main = async () => {
 console.log('start');
 const nums = await getNumbers();
 await asyncForEach(nums, async x => {
  const res = await doMulti(x)
  console.log(res)
 })
 console.log('end');
};
main();

四、Eslint 問題

這時(shí)候 Eslint 又報(bào)了錯(cuò):no-await-in-loop 。關(guān)于這一點(diǎn),Eslint 官方文檔 /tupian/20230522/no-await-in-loop 也做了說明。

好的寫法:

async function foo(things) {
 const results = [];
 for (const thing of things) {
  // Good: all asynchronous operations are immediately started.
  results.push(bar(thing));
 }
 // Now that all the asynchronous operations are running, here we wait until they all complete.
 return baz(await Promise.all(results));
}

不好的寫法:

async function foo(things) {
 const results = [];
 for (const thing of things) {
  // Bad: each loop iteration is delayed until the entire asynchronous operation completes
  results.push(await bar(thing));
 }
 return baz(results);
}

其實(shí)上面兩種寫法沒有什么好壞之分,這兩種寫法的結(jié)果是完全不一樣的。Eslint 推薦的 “好的寫法” 在執(zhí)行異步操作的時(shí)候沒有順序的,“不好的寫法” 中有順序,具體需要用哪種寫法還是要根據(jù)業(yè)務(wù)需求來決定。

所以,在文檔的 When Not To Use It 中,Eslint 也提到,如果需要有順序地執(zhí)行,我們是可以禁止掉該規(guī)則的:

In many cases the iterations of a loop are not actually independent of each-other. For example, the output of one iteration might be used as the input to another. Or, loops may be used to retry asynchronous operations that were unsuccessful. Or, loops may be used to prevent your code from sending an excessive amount of requests in parallel. In such cases it makes sense to use await within a loop and it is recommended to disable the rule via a standard ESLint disable comment.

上述就是小編為大家分享的await在forEach中不起作用如何解決了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁標(biāo)題:await在forEach中不起作用如何解決-創(chuàng)新互聯(lián)
本文URL:http://jinyejixie.com/article0/djceio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊、外貿(mào)網(wǎng)站建設(shè)、品牌網(wǎng)站建設(shè)、虛擬主機(jī)、品牌網(wǎng)站制作小程序開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)
乌鲁木齐县| 盘锦市| 绥芬河市| 石棉县| 九江市| 祥云县| 禹城市| 宝鸡市| 潼关县| 屏山县| 桑植县| 新巴尔虎右旗| 龙川县| 哈尔滨市| 高尔夫| 岳阳县| 定边县| 泰兴市| 资兴市| 武功县| 海盐县| 塔城市| 永嘉县| 宜良县| 隆尧县| 乳山市| 小金县| 拉孜县| 咸阳市| 吉木乃县| 乌审旗| 溧水县| 睢宁县| 元氏县| 四平市| 靖江市| 苏尼特左旗| 乐陵市| 金华市| 蒙城县| 安平县|