在我的react应用程序中,我有一个函数在某种程度上模拟了对API的调用。有没有办法可以在此API请求之后同步运行回调函数,以使我的数据按发送顺序返回?
// the order in the array here matters
const wordTypeArr = ['type1', 'type2', 'type3']
// loop sequentially through array
wordTypeArr.forEach((v,i) => {
getRandomWordFromAPI(v, addWord)
})
//simulated "API" - can't modify this function
const getRandomWordFromAPI = (type, callback) => {
return setTimeout(function() {
callback(
type in dictionary ?
sample(dictionary[type]) :
null
);
}, (Math.random() * 750 + 250));
}
//callback runs after response - update the state
const addWord = (val) => {
const newState = wordList
newState.push(val)
setWordList(newState);
}
如您所见,getRandomWordFromAPI
函数返回一个超时函数,然后在超时后异步(无序)执行回调。这是不可取的,因为我的结果必须井然有序。
也许我需要将addWord
包装在一个诺言中?或类似的东西?
答案 0 :(得分:2)
更改该功能确实是首选,因为它将使代码更易于阅读。但是由于可以向getRandomWordFromAPI
发送回调,所以可以将resolve函数作为回调而不是addWord()发送,然后将addWord链接到解决方案。
由于我们没有字典对象,因此我将代码的某些部分放在注释中,但是结构保持不变。
// the order in the array here matters
const wordTypeArr = ['type1', 'type2', 'type3'];
//simulated "API" - can't modify this function
const getRandomWordFromAPI = (type, callback) => {
return setTimeout(function() {
callback( type );
/*
callback(
type in dictionary ?
sample(dictionary[type]) :
null
);*/
}, (Math.random() * 750 + 250));
}
//callback runs after response - update the state
const addWord = (val) => {
console.log( val );
/*
const newState = wordList
newState.push(val)
setWordList(newState);
*/
}
const randomWords = wordTypeArr.map( word => {
return new Promise(( resolve, reject ) => {
getRandomWordFromAPI( word, resolve );
});
});
Promise.all( randomWords ).then( words => words.forEach( addWord ));
答案 1 :(得分:0)
现在是2019年,承诺已经兑现,回调已经结束。更严重的是,这是您如何重构代码以使其按您希望的方式工作的方法:
// mock the API
const getRandomWordFromAPI = (type, callback) => {
setTimeout(() => {
let word = `some-word-of-type-${type}`;
callback(word);
}, 1000)
}
// promisify the mocked API
const getRandomWordFromAPIPromise = (type) => new Promise(resolve => {
getRandomWordFromAPI(type, resolve);
});
// fetch all data asynchronously, in order
const wordTypeArr = ['type1', 'type2', 'type3'];
const promises = wordTypeArr.map(getRandomWordFromAPIPromise);
Promise.all(promises).then(words => {
// do whatever you want with the words
console.log(words)
});