Array.forEach
JavaScript 의 기본 구현에 관한 질문이 있습니다. 비동기 적으로 작동합니까? 예를 들어, 내가 전화하면 :
[many many elements].forEach(function () {lots of work to do})
이것이 차단되지 않습니까?
답변
아니요, 차단 중입니다. 알고리즘 의 사양을 살펴보십시오 .
그러나 MDN에서는 구현을 이해하기가 더 쉽습니다 .
if (!Array.prototype.forEach)
{
Array.prototype.forEach = function(fun /*, thisp */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (typeof fun !== "function")
throw new TypeError();
var thisp = arguments[1];
for (var i = 0; i < len; i++)
{
if (i in t)
fun.call(thisp, t[i], i, t);
}
};
}
각 요소에 대해 많은 코드를 실행해야하는 경우 다른 접근 방식을 사용해야합니다.
function processArray(items, process) {
var todo = items.concat();
setTimeout(function() {
process(todo.shift());
if(todo.length > 0) {
setTimeout(arguments.callee, 25);
}
}, 25);
}
그런 다음 호출하십시오.
processArray([many many elements], function () {lots of work to do});
그러면 차단되지 않을 것입니다. 이 예제는 고성능 JavaScript 에서 가져온 것입니다 .
또 다른 옵션은 웹 워커 일 수 있습니다 .
답변
비동기 친화적 인 버전 Array.forEach
과 비슷한 버전이 필요하면 Node.js ‘async’모듈에서 사용할 수 있습니다 : http://github.com/caolan/async …이 모듈은 브라우저에서도 작동합니다 .
async.each(openFiles, saveFile, function(err){
// if any of the saves produced an error, err would equal that error
});
답변
노드에서 실제로 무거운 계산을 수행하는 데 공통적 인 패턴이 있습니다.
노드는 단일 스레드입니다 (고의적 인 디자인 선택 으로 Node.js 란 무엇입니까? 참조 ). 이는 단일 코어 만 사용할 수 있음을 의미합니다. 최신 상자에는 8 개, 16 개 또는 더 많은 코어가 있으므로 시스템의 90 % 이상이 유휴 상태가 될 수 있습니다. REST 서비스의 공통 패턴은 코어 당 하나의 노드 프로세스를 시작하여 http://nginx.org/ 와 같은 로컬로드 밸런서 뒤에 배치하는 것 입니다.
아이를 포크 -당신이하려고하는 일에 대해, 무거운 리프팅을하기 위해 아이 프로세스를 포크하는 또 다른 일반적인 패턴이 있습니다. 단점은 자식 프로세스가 백그라운드에서 많은 계산을 수행 할 수 있고 부모 프로세스는 다른 이벤트에 응답 할 수 있다는 것입니다. 중요한 것은이 하위 프로세스와 메모리를 공유 할 수 없거나 공유해서는 안된다는 것입니다 (많은 왜곡과 일부 고유 코드가없는 경우는 아님). 메시지를 전달해야합니다. 입력 및 출력 데이터의 크기가 수행해야하는 계산에 비해 작 으면 아름답게 작동합니다. 하위 node.js 프로세스를 시작하고 이전에 사용한 것과 동일한 코드를 사용할 수도 있습니다.
예를 들면 다음과 같습니다.
var child_process = require ( 'child_process'); run_in_child 함수 (배열, cb) { var process = child_process.exec ( 'node libfn.js', function (err, stdout, stderr) { var output = JSON.parse (stdout); cb (err, 출력); }); process.stdin.write (JSON.stringify (array), 'utf8'); process.stdin.end (); }
답변
Array.forEach
는 대기하지 않는 컴퓨팅 작업을위한 것이며 이벤트 루프에서 계산을 비동기식으로 수행 할 수있는 것은 없습니다 (멀티 코어 계산이 필요한 경우 웹 워커가 멀티 프로세싱을 추가 함). 여러 작업이 끝날 때까지 기다리려면 카운터를 사용하십시오. 카운터는 세마포어 클래스로 랩핑 할 수 있습니다.
답변
2018-10-11 편집 : 아래 설명 된 표준을 통과하지 못할 가능성이 높은 것처럼 보입니다. 파이프 라인 을 대안으로 고려하십시오 (정확하게 동일하게 작동하지 않지만 비슷한 매너로 메소드를 구현할 수 있음).
이것이 바로 es7에 대해 흥분되는 이유입니다. 미래에 아래 코드와 같은 작업을 수행 할 수 있습니다 (일부 사양은 완전하지 않으므로주의해서 사용하십시오.이 최신 정보를 유지하려고 노력할 것입니다). 그러나 기본적으로 new :: bind 연산자를 사용하면 객체의 프로토 타입에 메소드가 포함 된 것처럼 객체에서 메소드를 실행할 수 있습니다. 예 : [Object] :: [Method] 일반적으로 [Object]를 호출합니다. [ObjectsMethod]
오늘 (24-July-16)이 작업을 수행하고 모든 브라우저에서 작동하게하려면 가져 오기 / 내보내기 , 화살표 함수 , 약속 , 비동기 / 대기 및 가장 중요한 함수 바인딩 과 같은 기능을 위해 코드를 변환해야합니다 . 필요한 경우 함수 바인드 만 사용하도록 아래 코드를 수정할 수 있습니다 . 이 모든 기능은 babel 을 사용하여 깔끔하게 사용할 수 있습니다 .
YourCode.js (여기서 ‘ 많은 작업 수행 ‘은 단순히 비동기 작업이 완료되면이를 해결하여 약속을 반환해야합니다.)
import { asyncForEach } from './ArrayExtensions.js';
await [many many elements]::asyncForEach(() => lots of work to do);
ArrayExtensions.js
export function asyncForEach(callback)
{
return Promise.resolve(this).then(async (ar) =>
{
for(let i=0;i<ar.length;i++)
{
await callback.call(ar, ar[i], i, ar);
}
});
};
export function asyncMap(callback)
{
return Promise.resolve(this).then(async (ar) =>
{
const out = [];
for(let i=0;i<ar.length;i++)
{
out[i] = await callback.call(ar, ar[i], i, ar);
}
return out;
});
};
답변
타사 라이브러리가 필요없는 짧은 비동기 함수입니다.
Array.prototype.each = function (iterator, callback) {
var iterate = function () {
pointer++;
if (pointer >= this.length) {
callback();
return;
}
iterator.call(iterator, this[pointer], iterate, pointer);
}.bind(this),
pointer = -1;
iterate(this);
};
답변
npm 에는 각 루프마다 쉽게 비 동기화 할 수있는 패키지가 있습니다 .
var forEachAsync = require('futures').forEachAsync;
// waits for one request to finish before beginning the next
forEachAsync(['dogs', 'cats', 'octocats'], function (next, element, index, array) {
getPics(element, next);
// then after all of the elements have been handled
// the final callback fires to let you know it's all done
}).then(function () {
console.log('All requests have finished');
});
AllAsync의 또 다른 변형