链接承诺,包括获取
Chaining promises including fetch
我有一个以文件作为输入的 React 表单,onFileChange
保存 setFile(e.target.files[0])
(并且还切换布尔值 change
)。然后当我提交表格时:
- 我首先想把这个文件上传到云端(这里是Cloudinary),
- 等待响应对象(即我要找的
url
和public_id
)
- 然后我将此对象(
url
和 'public_id
)添加到表单数据,然后 post 到数据库后端。
我认为链接承诺应该可以完成这项工作,但我做不到。
在我的 onFormSubmit
中,我首先定义了一个捕获 none 异步数据的承诺:
function init(fd){
fd.append('input1'...)
return Promise.resolve(fd)
}
所以我可以重用表单数据来提供下一个承诺 upLoadToCL
应该 'normally' 将响应对象从云异步附加到表单数据,其中:
init(new FormData).then(res => upLoadToCL(res)).then(res=> ...)
function upLoadToCL(fd) {
if (changed) {
// send 'file' (saved as state variable after input) to the cloud
const newfd = new FormData();
newfd.append("file", file);
newfd.append("upload_preset", "ml_default");
fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
method: "POST",
body: newfd,
})
.then((res) => res.json())
// append the formdata argument 'fd' with the result
.then((res) => {
setPhoto(res);
fd.append("event[directCLUrl]", res.url);
fd.append("event[publicID]", res.public_id);
})
.catch((err) => {
throw new Error(err);
});
return Promise.resolve(fd);
}
}
我检查了第一个承诺是否有效,并向第二个承诺发送了一个 'prefilled' 表单数据。然后 post 请求起作用,并且 returns 响应,因为我可以看到状态变量 photo
在未来的某个时间更新。然而,promise 本身 returns 一个无效的表单数据,即使没有链接:
upLoadToCL(new FormData())
.then(res=> {
for (let [k,v] of res){
console.log(k,v)
}
})
returns 没有。
您已经很好地执行了 promise 链接。您只需要 return 该承诺链的结果而不是来自您的函数的 Promise.resolve(fd)
:
function upLoadToCL(fd) {
if (changed) {
// send 'file' (saved as state variable after input) to the cloud
const newfd = new FormData();
newfd.append("file", file);
newfd.append("upload_preset", "ml_default");
return fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
// ^^^^^^
method: "POST",
body: newfd,
})
.then((res) => res.json())
.then((res) => {
setPhoto(res);
// append the formdata argument 'fd' with the result
fd.append("event[directCLUrl]", res.url);
fd.append("event[publicID]", res.public_id);
return fd;
// ^^^^^^ fulfilling the promise with the updated fd
});
} else {
return Promise.resolve(fd);
// ^^^^^^ always returning a promise for fd from uploadToCL()
}
}
我有一个以文件作为输入的 React 表单,onFileChange
保存 setFile(e.target.files[0])
(并且还切换布尔值 change
)。然后当我提交表格时:
- 我首先想把这个文件上传到云端(这里是Cloudinary),
- 等待响应对象(即我要找的
url
和public_id
) - 然后我将此对象(
url
和'public_id
)添加到表单数据,然后 post 到数据库后端。
我认为链接承诺应该可以完成这项工作,但我做不到。
在我的 onFormSubmit
中,我首先定义了一个捕获 none 异步数据的承诺:
function init(fd){
fd.append('input1'...)
return Promise.resolve(fd)
}
所以我可以重用表单数据来提供下一个承诺 upLoadToCL
应该 'normally' 将响应对象从云异步附加到表单数据,其中:
init(new FormData).then(res => upLoadToCL(res)).then(res=> ...)
function upLoadToCL(fd) {
if (changed) {
// send 'file' (saved as state variable after input) to the cloud
const newfd = new FormData();
newfd.append("file", file);
newfd.append("upload_preset", "ml_default");
fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
method: "POST",
body: newfd,
})
.then((res) => res.json())
// append the formdata argument 'fd' with the result
.then((res) => {
setPhoto(res);
fd.append("event[directCLUrl]", res.url);
fd.append("event[publicID]", res.public_id);
})
.catch((err) => {
throw new Error(err);
});
return Promise.resolve(fd);
}
}
我检查了第一个承诺是否有效,并向第二个承诺发送了一个 'prefilled' 表单数据。然后 post 请求起作用,并且 returns 响应,因为我可以看到状态变量 photo
在未来的某个时间更新。然而,promise 本身 returns 一个无效的表单数据,即使没有链接:
upLoadToCL(new FormData())
.then(res=> {
for (let [k,v] of res){
console.log(k,v)
}
})
returns 没有。
您已经很好地执行了 promise 链接。您只需要 return 该承诺链的结果而不是来自您的函数的 Promise.resolve(fd)
:
function upLoadToCL(fd) {
if (changed) {
// send 'file' (saved as state variable after input) to the cloud
const newfd = new FormData();
newfd.append("file", file);
newfd.append("upload_preset", "ml_default");
return fetch(`https://api.cloudinary.com/v1_1/${cloudName}/upload`, {
// ^^^^^^
method: "POST",
body: newfd,
})
.then((res) => res.json())
.then((res) => {
setPhoto(res);
// append the formdata argument 'fd' with the result
fd.append("event[directCLUrl]", res.url);
fd.append("event[publicID]", res.public_id);
return fd;
// ^^^^^^ fulfilling the promise with the updated fd
});
} else {
return Promise.resolve(fd);
// ^^^^^^ always returning a promise for fd from uploadToCL()
}
}