如何在promise之间异步传递数据?
How to pass data between promise asynchronously?
我想从后端获取几个数据并在加载时最后处理它们。现在,当这段代码运行时,data1 和 data2 是未定义的。我想等他们,但我不知道如何保持我的代码干净。我不确定 Promise.all() 是否适合这里,因为我需要专门保存 data1 和 data2 的值,而且我无法编写通用代码来解析 Promise.all()。
return new Promise( (resolve,reject) => {
let data1;
let data2;
let url1 = "http://fakeapi.com/getData1";
fetch(url1)
.then(res => res.json())
.then(data => data1SpecificAction())
.then(data => data1 = data)
.catch("cannot fetch data1")
let url2 = "http://fakeapi.com/getData2";
fetch(url2)
.then(res => res.json())
.then(data => data2 = data)
.catch("cannot fetch data2")
if(data1 && data2) {
resolve()
}
else {
reject()
}
}
如何修复此代码段?
解决方案是将我的具体操作放入另一个承诺中并使用 promise.all
return new Promise( (resolve,reject) => {
let data1;
let data2;
let promise1 = new Promise( (resolve,reject) => {
let url1 = "http://fakeapi.com/getData1";
fetch(url1)
.then(res => res.json())
.then(data => data1SpecificAction())
.then(data => {
data1 = data;
resolve()
}
.catch(()=>reject("cannot fetch data1"))
})
let promise 2 = new Promise( (resolve,reject) => {
let url2 = "http://fakeapi.com/getData2";
fetch(url2)
.then(res => res.json())
.then(data => {
data2 = data;
resolve()
}
)
.catch(()=>reject("cannot fetch data2"))
})
Promise.all([promise1,promise2])
.then(
() => {
if(data1 && data2) {
resolve()
}
else {
reject()
}
}
)
here 是 link 解释如何在 promise 之间传递数据。
您的问题或答案中不需要太多内容。你可以这样做:
const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
fetch(url1).then(res => res.json()).then(data1SpecificAction),
fetch(url2).then(res => res.json())
]).then([data1, data2] => {
if (data1 && data2) return; // resolve
// reject with appropriate error
let msg = data1 ? "missing data2" : "missing data1";
throw new Error(msg);
});
您的问题和答案中不需要做的事情:
- 不要将现有的承诺包装在另一个手动创建的承诺中。这被认为是一种反模式,因为根本不需要手动创建的承诺。你可以 return 你已经拥有的承诺。
- 不要将
.then()
结果分配给更高范围的变量。虽然偶尔会有这样的原因,但这不是其中之一,通常是您做错事的警告信号。
我发现 fetch()
界面有一些令人烦恼的地方,我发现这些界面经常受益于辅助函数(例如 404 状态解析,而不是拒绝):
function fetchJson(...args) {
return fetch(...args).then(res => {
if (!res.ok) throw new Error(`Got ${res.status} status`);
return res.json();
});
}
const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
fetchJson(url1).then(data1SpecificAction),
fetchJson(url2)
]).then([data1, data2] => {
if (data1 && data2) return; // resolve
// reject with appropriate error
let msg = data1 ? "missing data2" : "missing data1";
throw new Error(msg);
});
而且,在您想要拒绝结果为假的特定情况下,您甚至可以这样做:
function fetchJsonCheck(...args) {
return fetch(...args).then(res => {
if (!res.ok) throw new Error(`Got ${res.status} status`);
return res.json();
}).then(result => {
if (!result) throw new Error("empty result");
return result;
});
}
const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
fetchJsonCheck(url1).then(data1SpecificAction),
fetchJsonCheck(url2)
]);
我想从后端获取几个数据并在加载时最后处理它们。现在,当这段代码运行时,data1 和 data2 是未定义的。我想等他们,但我不知道如何保持我的代码干净。我不确定 Promise.all() 是否适合这里,因为我需要专门保存 data1 和 data2 的值,而且我无法编写通用代码来解析 Promise.all()。
return new Promise( (resolve,reject) => {
let data1;
let data2;
let url1 = "http://fakeapi.com/getData1";
fetch(url1)
.then(res => res.json())
.then(data => data1SpecificAction())
.then(data => data1 = data)
.catch("cannot fetch data1")
let url2 = "http://fakeapi.com/getData2";
fetch(url2)
.then(res => res.json())
.then(data => data2 = data)
.catch("cannot fetch data2")
if(data1 && data2) {
resolve()
}
else {
reject()
}
}
如何修复此代码段?
解决方案是将我的具体操作放入另一个承诺中并使用 promise.all
return new Promise( (resolve,reject) => {
let data1;
let data2;
let promise1 = new Promise( (resolve,reject) => {
let url1 = "http://fakeapi.com/getData1";
fetch(url1)
.then(res => res.json())
.then(data => data1SpecificAction())
.then(data => {
data1 = data;
resolve()
}
.catch(()=>reject("cannot fetch data1"))
})
let promise 2 = new Promise( (resolve,reject) => {
let url2 = "http://fakeapi.com/getData2";
fetch(url2)
.then(res => res.json())
.then(data => {
data2 = data;
resolve()
}
)
.catch(()=>reject("cannot fetch data2"))
})
Promise.all([promise1,promise2])
.then(
() => {
if(data1 && data2) {
resolve()
}
else {
reject()
}
}
)
here 是 link 解释如何在 promise 之间传递数据。
您的问题或答案中不需要太多内容。你可以这样做:
const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
fetch(url1).then(res => res.json()).then(data1SpecificAction),
fetch(url2).then(res => res.json())
]).then([data1, data2] => {
if (data1 && data2) return; // resolve
// reject with appropriate error
let msg = data1 ? "missing data2" : "missing data1";
throw new Error(msg);
});
您的问题和答案中不需要做的事情:
- 不要将现有的承诺包装在另一个手动创建的承诺中。这被认为是一种反模式,因为根本不需要手动创建的承诺。你可以 return 你已经拥有的承诺。
- 不要将
.then()
结果分配给更高范围的变量。虽然偶尔会有这样的原因,但这不是其中之一,通常是您做错事的警告信号。
我发现 fetch()
界面有一些令人烦恼的地方,我发现这些界面经常受益于辅助函数(例如 404 状态解析,而不是拒绝):
function fetchJson(...args) {
return fetch(...args).then(res => {
if (!res.ok) throw new Error(`Got ${res.status} status`);
return res.json();
});
}
const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
fetchJson(url1).then(data1SpecificAction),
fetchJson(url2)
]).then([data1, data2] => {
if (data1 && data2) return; // resolve
// reject with appropriate error
let msg = data1 ? "missing data2" : "missing data1";
throw new Error(msg);
});
而且,在您想要拒绝结果为假的特定情况下,您甚至可以这样做:
function fetchJsonCheck(...args) {
return fetch(...args).then(res => {
if (!res.ok) throw new Error(`Got ${res.status} status`);
return res.json();
}).then(result => {
if (!result) throw new Error("empty result");
return result;
});
}
const url1 = "http://fakeapi.com/getData1";
const url2 = "http://fakeapi.com/getData2";
return Promise.all([
fetchJsonCheck(url1).then(data1SpecificAction),
fetchJsonCheck(url2)
]);