在等待json响应时未捕获promise



我第一次在JS中实现Promises,在运行以下代码时,控制台日志中出现了未捕获的promise异常。

function data_present() {
return new Promise((resolve, reject) => {
fetch(api)
.then(response => response.json())
.then(message => { 
console.log(message)
if(message && Object.keys(message).length != 0) {
resolve()
}
else {
reject()
}
})
})
}

我在主函数中处理promise返回值的结果,如下所示,但还没有得到未捕获的promise消息:

function main() {
data_present().then(() => {
load_graph()
}).catch(() => {
data_present()
})
}

data_present((背后的逻辑是等待,直到我们在API端点得到一个非空的JSON响应,并在JSON响应为空时继续轮询它。

我得到的例外如下:

Uncaught (in promise) undefined
(anonymous) @ index.js:34
Promise.then (async)
(anonymous) @ index.js:29
data_present @ index.js:26
(anonymous) @ index.js:56
Promise.catch (async)
getParametersData @ index.js:55
onclick @ (index):92

您可以考虑使用一个函数从API获取、解析和返回JSON(无需将fetch包装在promise中,因为它已经返回了一个(,并使用轮询函数检查返回的数据。如果正确,则调用一个函数,否则再次轮询getData。如果有API错误日志。

我在这里使用了async/await,但原理是一样的。

// Simulates an API
// If the random number is a modulo of 5 set data
// to an object with a key/value pair, otherwise
// it set it to an empty object. If the random number
// is a modulo of 9 send an error, otherwise send the data.
function mockFetch() {
return new Promise((res, rej) => {
const rnd = Math.floor(Math.random() * 20);
const data = rnd % 5 === 0 ? { name: 'Bob' } : {};
setTimeout(() => {
if (rnd % 9 === 0) rej('Connection error');
res(JSON.stringify(data));
}, 2000);
});
}
// `getData` simply gets a response from the API and parses it.
// I had to use JSON.parse here rather that await response.json()
// because I'm not using the actual fetch API.
async function getData() {
const response = await mockFetch();
return JSON.parse(response);
}
// The `poll` function does all the heavy-lifting
// first we initialise `count`
async function poll(count = 1) {
console.log(`Polling ${count}`);
// Try and get some data. If it's not an empty object
// log the name (or in your case call loadGraph),
// otherwise poll the API again after two seconds.
// We wrap everything in a `try/catch`.
try {
const data = await getData();
if (data && data.name) {
console.log(data.name); // loadGraph
} else {
setTimeout(poll, 2000, ++count);
}
// If the API sends an error log that instead
// and poll again after five seconds
} catch (err) {
console.log(`${err}. Polling again in 5 seconds.`);
setTimeout(poll, 5000, 1);
}
}
poll();

这是基于戴回答的版本:

function mockFetch() {
return new Promise((res, rej) => {
const rnd = Math.floor(Math.random() * 20);
const data = rnd % 5 === 0 ? { name: 'Bob' } : {};
setTimeout(() => {
if (rnd % 9 === 0) rej('Connection error');
res(JSON.stringify(data));
}, 2000);
});
}
async function getData() {
const response = await mockFetch();
return JSON.parse(response);
}
async function delay(time) {
return new Promise(res => setTimeout(res, time));
}
async function poll(count = 1) {
do {
console.log(`Polling ${count}`);
try {
const data = await getData();
if (data && data.name) return data;
await delay(2000);
} catch (err) {
console.log(`${err}. Polling again in 5 seconds.`);
await delay(5000);
}
++count;
} while (count < 10);
console.log(`Reached poll limit - ${count}.`);
return false;
}
async function main() {
console.log('First');
console.log(await poll());
console.log('Second');
}
main();

而且fetch已经返回了一个promise。所以你不应该再把它包起来(我把它包括在我的例子中(。错误来自对下面的第二个catch块中描述的函数的第二次调用

function data_present() {
return fetch(api)
.then(response => response.json())
.then(message => {
console.log(message)
if (!message || Object.keys(message).length === 0) {
throw new Error('something went wrong');
} 
})
}
function main() {
data_present()
.then(() => {
load_graph()
}).catch(() => {
return data_present() // the promise which is returned here was not caught in your example
})
.catch(() => {
// another error
})
}

最新更新