redux thunk - 承诺完成后如何在嵌套数组中调度数据
Posted
技术标签:
【中文标题】redux thunk - 承诺完成后如何在嵌套数组中调度数据【英文标题】:redux thunk - how dispatch data in nested array after promise finish 【发布时间】:2017-04-09 01:43:20 【问题描述】:我想将 newArray 中的所有“默认文本”转换为“新文本”。然后用“新文本”分派数组。问题是调度函数正在调度“默认文本”。看起来它不等待承诺。下面代码中我的 promise 设置有什么问题?
return dispatch =>
let newarray =[
post:[ message:'default text', message:'default text']
]
let quests = newarray.map( (i) =>
return i.post.map( (item) =>
return axios.get(someLink).then( result =>
item.message = 'new text'
return result
)
)
)
Promise.all(quests).then( () =>
dispatch(
type: constant.GET_SUCCESS,
payload: newarray
)
).catch( () =>
console.log('no result')
)
【问题讨论】:
正如所写,映射过程不可能导致“得到我想要的数组”。如果在某个时间点console.log(array)
记录了您的预期,那么 (a) 它是较早事件转折的产物,或者 (b) 您正在运行与您发布的内容不同的内容。
实际上数组的外观并不重要。我只想发送修改后的数据。知道承诺有什么问题吗?
【参考方案1】:
你的输入数据结构是这样的:
[
post: [
message:'default text',
message:'default text'
]
]
您的代码将其转换为:
[
[
Promise<Axios>,
Promise<Axios>
]
]
因此,在外部层面,无法知道内部承诺何时完成。我们需要额外的承诺层来将这些信息向上移动到对象图中。本质上,我们需要:
Promise<[
Promise<[
Promise<Axios>,
Promise<Axios>
]>
]>
因此,当所有内部承诺都完成时,***承诺可以解决。执行此操作的代码看起来非常相似:
return function ()
var newarray = [ post: [ message: 'default text' , message: 'default text' ] ];
return Promise.all(newarray.map(function (i)
return Promise.all(i.post.map(function (item)
return axios.get(someLink).then(function (result)
item.message = 'new text';
);
));
)).then(function ()
return
type: constant.GET_SUCCESS,
payload: newarray
;
).catch(function (error)
return
type: constant.GET_ERROR,
payload: 'no result ' + error
;
);
;
如果你认为可以提高清晰度,你可以使用箭头函数(我没有):
return () =>
var newarray = [ post: [ message: 'default text' , message: 'default text' ] ];
return Promise.all(newarray.map( i => Promise.all(
i.post.map( item => axios.get(someLink).then( result =>
item.message = 'new text';
) )
))).then( () => (
type: constant.GET_SUCCESS,
payload: newarray
)).catch( (error) => (
type: constant.GET_ERROR,
payload: 'no result ' + error
));
;
一般说明:我已从您的代码中删除了回调函数。它与 promise 背后的哲学相矛盾,即从它们内部调用代码延续回调。
而不是这样做(基本上是您的代码):
function bla(callback)
asyncFunction().then(someProcessing).then(callback);
这样做:
function blaAsync()
return asyncFunction().then(someProcessing);
注意第二个变体如何不再依赖于它的调用者。它只是执行其任务并返回结果。调用者可以决定如何处理它:
blaAsync().then(function (result)
// what "callback" would do
)
【讨论】:
【参考方案2】:嵌套、异步和克隆(或模仿)的要求使这有点棘手:
您可以将所需的数组构建为外部变量:
function getMessagesAndDispatch(array)
try
let array_ = []; // outer variable, mimicking `array`
let outerPromises = array.map((a, i) =>
array_[i] = 'post': [] ; // mimicking `a`
let innerPromises = a.post.map((item, j) =>
array_[i].post[j] = ; // mimicking `item`
return axios.get(getOpenGraphOfThisLink + item.message).then(result =>
array_[i].post[j].message = result.data;
).catch((e) =>
array_[i].post[j].message = 'default text';
);
);
return Promise.all(innerPromises);
);
return Promise.all(outerPromises).then(() =>
dispatch(
'type': constant.GET_SUCCESS,
'payload': array_
);
).catch((e) =>
console.log('no result');
throw e;
);
catch(e)
// in case of a synchronous throw.
return Promise.reject(e);
或者,可以省去外部变量并允许承诺传达数据:
function getMessagesAndDispatch(array)
try
let outerPromises = array.map(a =>
let innerPromises = a.post.map((item) =>
return axios.get(getOpenGraphOfThisLink + item.message).then(result =>
return 'message': result.data ; // mimicking `item`
).catch((error) =>
return 'message': 'default text' ;
);
);
return Promise.all(innerPromises).then((items_) =>
return 'post': items_ ; // mimicking `a`
);
);
return Promise.all(outerPromises).then((array_) =>
dispatch(
'type': constant.GET_SUCCESS,
'payload': array_ // mimicking `array`
);
).catch((e) =>
console.log('no result');
throw e;
);
catch(e)
// in case of a synchronous throw.
return Promise.reject(e);
除非我犯了错误,否则两个版本都应该可以工作。
如果需要,在错误时注入默认值可能会更全面。
【讨论】:
以上是关于redux thunk - 承诺完成后如何在嵌套数组中调度数据的主要内容,如果未能解决你的问题,请参考以下文章