使用闭包净化通过递归构建对象的函数 — JavaScript
Use closure to purify a function which builds an object through recursion — JavaScript
我创建了一个基于 promise 的函数,该函数沿层次结构向上爬行,直到到达顶部,然后使用包含该结构的对象进行解析。我对代码的唯一抱怨是我修改了函数体之外的变量,这意味着它不是一个纯函数。我研究了 JavaScript 闭包,并且完全掌握了它们的琐碎用途。但我正在努力弄清楚 how/if 它们可以帮助使我的函数变得纯净。到目前为止,我尝试关闭的尝试只是覆盖了变量,而没有修改它们。这是使用全局变量的有问题的代码:
/* I want to move these variables inside function body to purify 'getPriorRows'*/
let priorRows = {}, level = 0;
const getPriorRows = id => new Promise(resolve => {
fetch(`/api/org/${id}`).then(result => {
/* global varaiables are modified here */
priorRows[level++] = result;
if (result.parentID) resolve(getPriorRows(result.parentID));
else resolve(priorRows);
});
});
getPriorRows('123432').then(result => console.log(result));
非常感谢任何关于此事的意见。
您应该能够将整个函数及其 "external" 变量包含在一个新函数中:
function getPriorRows(id) {
let priorRows = {}, level = 0;
const getNext = id => new Promise(
...
);
return getNext(id);
}
也就是说,您在每次迭代中创建的显式 new Promise
是一个 Promise 反模式:
function getPriorRows(id) {
let priorRows = {}, level = 0;
const getNext = id => fetch(`/api/org/${id}`).then(result => {
priorRows[level++] = result
if (result.parentID) {
return getNext(result.parentID));
} else {
return priorRows;
}
});
return getNext(id);
}
无论哪种方式,像这样包装状态的优点是您现在可以多次调用 getPriorRows
并行进行而不会相互干扰。
EDIT 编辑第二个代码以修复递归的复制和粘贴错误 - 您必须递归调用内部函数,而不是外部函数。
将值作为参数传递:
function getPriorRows(id, priorRows = {}, level = 0) {
return fetch(`/api/org/${id}`).then(result => {
/* global varaiables are modified here */
priorRows[level] = result;
if (result.parentID) return getPriorRows(result.parentID, priorRows, level+1);
else return priorRows;
});
}
getPriorRows('123432').then(result => console.log(result));
您可以使用默认参数或包装函数,甚至不需要闭包:
function getAll(id) { return getPriorRows(id, {}, 0); }
我还删除了 Promise
constructor antipattern。
我创建了一个基于 promise 的函数,该函数沿层次结构向上爬行,直到到达顶部,然后使用包含该结构的对象进行解析。我对代码的唯一抱怨是我修改了函数体之外的变量,这意味着它不是一个纯函数。我研究了 JavaScript 闭包,并且完全掌握了它们的琐碎用途。但我正在努力弄清楚 how/if 它们可以帮助使我的函数变得纯净。到目前为止,我尝试关闭的尝试只是覆盖了变量,而没有修改它们。这是使用全局变量的有问题的代码:
/* I want to move these variables inside function body to purify 'getPriorRows'*/
let priorRows = {}, level = 0;
const getPriorRows = id => new Promise(resolve => {
fetch(`/api/org/${id}`).then(result => {
/* global varaiables are modified here */
priorRows[level++] = result;
if (result.parentID) resolve(getPriorRows(result.parentID));
else resolve(priorRows);
});
});
getPriorRows('123432').then(result => console.log(result));
非常感谢任何关于此事的意见。
您应该能够将整个函数及其 "external" 变量包含在一个新函数中:
function getPriorRows(id) {
let priorRows = {}, level = 0;
const getNext = id => new Promise(
...
);
return getNext(id);
}
也就是说,您在每次迭代中创建的显式 new Promise
是一个 Promise 反模式:
function getPriorRows(id) {
let priorRows = {}, level = 0;
const getNext = id => fetch(`/api/org/${id}`).then(result => {
priorRows[level++] = result
if (result.parentID) {
return getNext(result.parentID));
} else {
return priorRows;
}
});
return getNext(id);
}
无论哪种方式,像这样包装状态的优点是您现在可以多次调用 getPriorRows
并行进行而不会相互干扰。
EDIT 编辑第二个代码以修复递归的复制和粘贴错误 - 您必须递归调用内部函数,而不是外部函数。
将值作为参数传递:
function getPriorRows(id, priorRows = {}, level = 0) {
return fetch(`/api/org/${id}`).then(result => {
/* global varaiables are modified here */
priorRows[level] = result;
if (result.parentID) return getPriorRows(result.parentID, priorRows, level+1);
else return priorRows;
});
}
getPriorRows('123432').then(result => console.log(result));
您可以使用默认参数或包装函数,甚至不需要闭包:
function getAll(id) { return getPriorRows(id, {}, 0); }
我还删除了 Promise
constructor antipattern。