Redux 中的递归函数
Recursive function in Redux
正在尝试传递对递归函数的引用以检查 Redux 操作数据获取是否完成,但出现函数引用错误
const fetchAccountComplete = (state, accountNo) => { //state here is function reference
return new Promise(resolve => {
(function waitForFetchComplete(state, accountNo) {
const {isFetching, receivedAt} = state().account[accountNo] // getting state not a function here
if (!isFetching) return resolve()
setTimeout(waitForFetchComplete, 100)
})()
})
}
有没有更好的方法 return 在 Redux 调度操作中对调用函数的承诺,以便在获取数据后,我需要在其他操作中执行一些其他逻辑。
更新 1:
应该更清楚了。此请求有两个调用方,接收对帐户数据的操作。第一个调用者的指示类似于上面的评论,所以等到完成,第二个调用者不会再次进行异步调用,并且需要检查数据获取是否完成,因此尝试查看是否具有检查状态的递归函数,以便 promise 可以正在解决中
您可以利用有前途的链接。
示例:
执行三个操作,例如:IS_FETCHING、FETCH_SUCCESS、FETCH_ERROR。
IS_FETCHING:
只会将您的状态设置为挂起(例如,可能对显示加载动画很有用)。
FETCH_SUCCESS:
将包含获取的结果以更新状态。还将清除 isUpdating 标志
FETCH_ERROR:
将包含由于提取(应用程序或网络错误)引起的任何可能的错误。还将清除 isUpdating 标志
那么,在应用层你可以做的是:
dispatch({type: IS_FETCHING, payload: data});
fetch(`https://MY-SERVER.com/?data=${data}`)
.then(response => response.json())
.then(json =>
dispatch({
type: isError(json) ? FETCH_RESULT : FETCH_ERROR,
payload: json
})
);
您甚至可以从动作创作者那里受益。
这是一个很好的指南:https://redux.js.org/advanced/async-actions
如果您有一个函数 returns 一个使用相同参数多次调用的 promise,那么您可以将其分组,这样当它仍然有一个未解决的 promise 时就不会调用该函数并且有些东西试图用相同的参数再次调用它。
这是一个例子:
//group promise returning function
const createGroup = (cache) => (
fn,
getKey = (...x) => JSON.stringify(x)
) => (...args) => {
const key = getKey(args);
let result = cache.get(key);
if (result) {
return result;
}
//no cache
result = Promise.resolve(fn.apply(null, args)).then(
(r) => {
cache.done(key); //tell cache promise is done
return r;
},
(e) => {
cache.done(key); //tell cache promise is done
return Promise.reject(e);
}
);
cache.set(key, result);
return result;
};
//creates a cache that will remove cached value when
// Promise is done (resolved or rejected)
const createCache = (cache = new Map()) => {
return {
get: (key) => cache.get(key),
set: (key, value) => cache.set(key, value),
done: (key) => cache.delete(key),
};
};
//function that retuns a promise
const later = (time, value) => {
console.log('executing later with values', time, value);
return new Promise((r) =>
setTimeout(() => r(value), time)
);
};
//create group function with a cache that will remove
// cache key when promise is resolved or rejected
const groupAndRemoveCacheOnDone = createGroup(
createCache()
);
//grouped version of the later function
const groupedLater = groupAndRemoveCacheOnDone(later);
//testing the groped later
groupedLater(100, 8); //first call causes console.log
groupedLater(100, 8); //same arguments will not call later
groupedLater(100, 8); //will not call later
//will call later because arguments are not the same
// as the other calls
groupedLater(100, 'XX');
groupedLater(100, 8) //will not call later
.then((value) => {
console.log('resolved with:', value);
//this will call later because cache value is removed
// after promise is resolved
return groupedLater(100, 8);
})
.then(() => {
//testing with fetchAccountComplete
console.log(
'***** how many times is fetchAccountComplete called *****'
);
const fetchAccountComplete = (state, accountNo) => {
console.log(
'fetchAccountComplete called with',
accountNo
);
return new Promise((resolve) => {
(function waitForFetchComplete(state, accountNo) {
const {
isFetching,
receivedAt,
} = state().account[accountNo]; // getting state not a function here
if (!isFetching) return resolve();
setTimeout(
() => waitForFetchComplete(state, accountNo),
100
);
})(state, accountNo);
});
};
const data = {
account: [{ isFetching: true }],
};
const state = () => data;
const groupedFetchAccountComplete = groupAndRemoveCacheOnDone(
fetchAccountComplete
);
groupedFetchAccountComplete(state, 0);
groupedFetchAccountComplete(state, 0);
groupedFetchAccountComplete(state, 0);
groupedFetchAccountComplete(state, 0).then((resolve) =>
console.log('resolved')
);
data.account[0].isFetching = false;
});
正在尝试传递对递归函数的引用以检查 Redux 操作数据获取是否完成,但出现函数引用错误
const fetchAccountComplete = (state, accountNo) => { //state here is function reference
return new Promise(resolve => {
(function waitForFetchComplete(state, accountNo) {
const {isFetching, receivedAt} = state().account[accountNo] // getting state not a function here
if (!isFetching) return resolve()
setTimeout(waitForFetchComplete, 100)
})()
})
}
有没有更好的方法 return 在 Redux 调度操作中对调用函数的承诺,以便在获取数据后,我需要在其他操作中执行一些其他逻辑。
更新 1:
应该更清楚了。此请求有两个调用方,接收对帐户数据的操作。第一个调用者的指示类似于上面的评论,所以等到完成,第二个调用者不会再次进行异步调用,并且需要检查数据获取是否完成,因此尝试查看是否具有检查状态的递归函数,以便 promise 可以正在解决中
您可以利用有前途的链接。 示例:
执行三个操作,例如:IS_FETCHING、FETCH_SUCCESS、FETCH_ERROR。
IS_FETCHING: 只会将您的状态设置为挂起(例如,可能对显示加载动画很有用)。
FETCH_SUCCESS: 将包含获取的结果以更新状态。还将清除 isUpdating 标志
FETCH_ERROR: 将包含由于提取(应用程序或网络错误)引起的任何可能的错误。还将清除 isUpdating 标志
那么,在应用层你可以做的是:
dispatch({type: IS_FETCHING, payload: data});
fetch(`https://MY-SERVER.com/?data=${data}`)
.then(response => response.json())
.then(json =>
dispatch({
type: isError(json) ? FETCH_RESULT : FETCH_ERROR,
payload: json
})
);
您甚至可以从动作创作者那里受益。 这是一个很好的指南:https://redux.js.org/advanced/async-actions
如果您有一个函数 returns 一个使用相同参数多次调用的 promise,那么您可以将其分组,这样当它仍然有一个未解决的 promise 时就不会调用该函数并且有些东西试图用相同的参数再次调用它。
这是一个例子:
//group promise returning function
const createGroup = (cache) => (
fn,
getKey = (...x) => JSON.stringify(x)
) => (...args) => {
const key = getKey(args);
let result = cache.get(key);
if (result) {
return result;
}
//no cache
result = Promise.resolve(fn.apply(null, args)).then(
(r) => {
cache.done(key); //tell cache promise is done
return r;
},
(e) => {
cache.done(key); //tell cache promise is done
return Promise.reject(e);
}
);
cache.set(key, result);
return result;
};
//creates a cache that will remove cached value when
// Promise is done (resolved or rejected)
const createCache = (cache = new Map()) => {
return {
get: (key) => cache.get(key),
set: (key, value) => cache.set(key, value),
done: (key) => cache.delete(key),
};
};
//function that retuns a promise
const later = (time, value) => {
console.log('executing later with values', time, value);
return new Promise((r) =>
setTimeout(() => r(value), time)
);
};
//create group function with a cache that will remove
// cache key when promise is resolved or rejected
const groupAndRemoveCacheOnDone = createGroup(
createCache()
);
//grouped version of the later function
const groupedLater = groupAndRemoveCacheOnDone(later);
//testing the groped later
groupedLater(100, 8); //first call causes console.log
groupedLater(100, 8); //same arguments will not call later
groupedLater(100, 8); //will not call later
//will call later because arguments are not the same
// as the other calls
groupedLater(100, 'XX');
groupedLater(100, 8) //will not call later
.then((value) => {
console.log('resolved with:', value);
//this will call later because cache value is removed
// after promise is resolved
return groupedLater(100, 8);
})
.then(() => {
//testing with fetchAccountComplete
console.log(
'***** how many times is fetchAccountComplete called *****'
);
const fetchAccountComplete = (state, accountNo) => {
console.log(
'fetchAccountComplete called with',
accountNo
);
return new Promise((resolve) => {
(function waitForFetchComplete(state, accountNo) {
const {
isFetching,
receivedAt,
} = state().account[accountNo]; // getting state not a function here
if (!isFetching) return resolve();
setTimeout(
() => waitForFetchComplete(state, accountNo),
100
);
})(state, accountNo);
});
};
const data = {
account: [{ isFetching: true }],
};
const state = () => data;
const groupedFetchAccountComplete = groupAndRemoveCacheOnDone(
fetchAccountComplete
);
groupedFetchAccountComplete(state, 0);
groupedFetchAccountComplete(state, 0);
groupedFetchAccountComplete(state, 0);
groupedFetchAccountComplete(state, 0).then((resolve) =>
console.log('resolved')
);
data.account[0].isFetching = false;
});