我必须一个接一个地执行三个fetch请求。也就是说,假设我的三个fetch请求是。
const A = (url) => (dispatch) => {
let req = fetch(url, ....)
.then(response => {
if (!response.ok) {
throw response;
}
return response.json();
}).then(response => {
}).catch(error => {
})
}
const B = (url) => (dispatch) => {
let req = fetch(url, ....)
.then(response => {
if (!response.ok) {
throw response;
}
return response.json();
}).then(response => {
}).catch(error => {
})
}
const C= (url) => (dispatch) => {
let req = fetch(url, ....)
.then(response => {
if (!response.ok) {
throw response;
}
return response.json();
}).then(response => {
}).catch(error => {
})
}
首先执行A,A完成后执行B,B完成后执行C,A、B、C完成后,我想执行一个函数:
doSomething = () => {
//do something after A, B, C are executed
}
我对 "承诺 "很陌生。谁能指导我怎么做?
以下是我的实际代码,我试了一下
const chopSegment = (token, frame_tag_url, tag_to_delete_id, chopped_tag_array, tags_for_index_update) => (dispatch) => {
let req = fetch(frame_tag_url + tag_to_delete_id + "/",
{
method: "DELETE",
headers: {
"Authorization": "Token " + token,
"content-type": "application/json"
}
})
req.then(response => {
if (!response.ok) {
throw response;
}
else
return response.json();
}).then(response => {
return fetch(frame_tag_url,
{
method: "POST",
headers: {
"Authorization": "Token " + token,
"content-type": "application/json",
},
body : JSON.stringify(tags_for_index_update)
}).then(response1 => {
if (!response1.ok) {
throw response1;
}
return response1.json();
}).then(response => {
for(let i = 0; i < chopped_tag_array.length; i++){
return fetch(frame_tag_url,
{
method: "POST",
body: JSON.stringify(chopped_tag_array[i]),
headers: {
"Authorization": "Token " + token,
"content-type": "application/json"
}
})
.then(response2 => {
if (!response2.ok) {
throw response2;
}
return response2.json();
}).then(response2 => {
dispatch(chopSegmentSuccess(response2))
}).catch(error => {
})
}
}).catch(error => {
})
}).catch(error => {
})
}
在上面的代码中,只有第一个fecth("DELETE")被执行。后续的fetch没有被执行。
看起来你的方向是对的。对于承诺,你通常希望让 .then
链尽可能的线性。下面是你对承诺链的正确做法(我重构了一些功能,以方便可读)。
const throwIfNotOk = response => {
if (!response.ok) throw response
return response
}
const deleteTag = (url, token) => fetch(url, {
method: "DELETE",
headers: {
"Authorization": "Token " + token,
"content-type": "application/json"
},
})
const postTagForIndexUpdate = (url, tag) => fetch(url, {
method: "POST",
headers: {
"Authorization": "Token " + token,
"content-type": "application/json"
},
body: JSON.stringify(tag),
})
const chopSegment = (
token,
frame_tag_url,
tag_to_delete_id,
chopped_tag_array,
tags_for_index_update,
) => dispatch => {
return deleteTag(frame_tag_url + tag_to_delete_id + "/")
.then(response => { return throwIfNotOk(response) })
.then(response => { return response.json() })
.then(() => {
return postTagForIndexUpdate(frame_tag_url, tags_for_index_update)
})
.then(response => { return throwIfNotOk(response) })
.then(response => { return response.json() })
.then(() => {
const promises = []
for (let i = 0; i < chopped_tag_array.length; i++) {
promises.push(
postTagForIndexUpdate(frame_tag_url, chopped_tag_array[i])
.then(response => { return throwIfNotOk(response) })
.then(response => { return response.json() })
)
}
return Promise.all(promises)
})
.then(response => { dispatch(response) })
.catch(error => {
// handle error
})
}
你可以通过使用一个承诺库,比如 卢比科
import { pipe, map } from 'rubico'
const chopSegment = (
token,
frame_tag_url,
tag_to_delete_id,
chopped_tag_array,
tags_for_index_update,
) => dispatch => pipe([
() => deleteTag(frame_tag_url + tag_to_delete_id + "/"),
throwIfNotOk,
response => response.json(),
() => postTagForIndexUpdate(frame_tag_url, tags_for_index_update),
throwIfNotOk,
response => response.json(),
() => chopped_tag_array,
map(pipe([
chopped_tag => postTagForIndexUpdate(frame_tag_url, chopped_tag),
throwIfNotOk,
response => response.json(),
])),
dispatch,
])
你应该在前一个的回调中(在 "then "里面)调用下面的 "fetches",或者连锁调用。fetch(...).then(...).then(...)...
你可以通过使用asyncawait关键字来改进语法。请大家看一下。
https:/developer.mozilla.orgen-USdocsWebJavaScriptReferenceStatementsasync_function。