我使用axios POST method
通过API使用连续的then
发布多个内容。
要修复硬编码的then
,我尝试使用for循环(使用let,for..of,Promise.all等),但无法正常工作
File "C:\Python\Python3.6.3\lib\wsgiref\simple_server.py", line 35, in close
self.status.split(' ',1)[0], self.bytes_sent
AttributeError: 'NoneType' object has no attribute 'split'
错误(Django后端)。
这是源代码(.vue文件)。
//defaultHttpClient is an axios call
const labelList = this.newLabel.text.split(" ");
this.copiedLabels = JSON.parse(JSON.stringify(this.newLabel));
async function putLabel(i, response, newLabel, copiedLabels, labels){
copiedLabels.text = newLabel.text.split(" ")[i]
await defaultHttpClient.post(`/v1/projects/${response.data.id}/labels`, copiedLabels)
//API call
}
//tried to make multiple API calls but this was the only way to make it possible.
defaultHttpClient.post('/v1/projects', payload)
.then((response) => {
window.location = `/projects/${response.data.id}/docs/create`;
return response;
})
.then((response)=> {
putLabel(0, response, this.newLabel, this.copiedLabels, this.labels);
return response;
})
.then((response)=> {
putLabel(1, response, this.newLabel, this.copiedLabels, this.labels);
return response;
})
.then((response)=> {
putLabel(2, response, this.newLabel, this.copiedLabels, this.labels);
return response;
})
我们如何简化硬编码的then
或使其更好地工作?
答案 0 :(得分:0)
您可以使用async
和await
进行简化:
async function someFunction() {
try {
let response = await defaultHttpClient.post('/v1/projects', payload)
await putLabel(0, response, this.newLabel, this.copiedLabels, this.labels);
await putLabel(1, response, this.newLabel, this.copiedLabels, this.labels);
await putLabel(2, response, this.newLabel, this.copiedLabels, this.labels);
window.location = `/projects/${response.data.id}/docs/create`;
} catch(e) {
// put some error handling code here
}
}
仅您所了解,原始代码根本无法使用。在您所有的window.location
调用都有机会执行之前,putLabel()
会更改当前页面。在将window.location
设置到新页面之前,您需要完成所有想要完成的工作。
此外,未对所有.then()
处理程序进行编码以使其按正确的顺序执行,因为它们没有一个等待每个putLabel()
完成。为此,您必须使用它们返回的承诺,但您只是忽略了这一点。
您可以将putLabel进一步简化为:
function putLabel(i, response, newLabel, copiedLabels, labels) {
copiedLabels.text = newLabel.text.split(" ")[i]
return defaultHttpClient.post(`/v1/projects/${response.data.id}/labels`, copiedLabels)
//API call
}
请务必记住,await
会暂停函数的内部执行,但是async
函数仍然会在击中第一个await
后立即返回promise。因此,您在await
中的putLabel()
并没有完成任何事情,也没有阻止putLabel()
在完成.post()
调用之前返回。
似乎也没有特别的原因,您的putLabel()
调用必须顺序执行,其中第二个等待第一个完成,并且它们可以全部并行运行。如果是这样,那么您可以这样运行它们:
async function someFunction() {
try {
let response = await defaultHttpClient.post('/v1/projects', payload)
await Promise.all([
putLabel(0, response, this.newLabel, this.copiedLabels, this.labels),
putLabel(1, response, this.newLabel, this.copiedLabels, this.labels),
putLabel(2, response, this.newLabel, this.copiedLabels, this.labels)
]);
window.location = `/projects/${response.data.id}/docs/create`;
} catch(e) {
// put some error handling code here
}
}
答案 1 :(得分:0)
const apicall = async () => {
const res1 = await defaultHttpClient.post('/v1/projects', payload)
window.location = `/projects/${res1.data.id}/docs/create`;
const res2 = putLabel(0, res1, this.newLabel, this.copiedLabels, this.labels);
const res3 = putLabel(1, res2, this.newLabel, this.copiedLabels, this.labels);
const res4 = putLabel(2, res3, this.newLabel, this.copiedLabels, this.labels);
return res4;
}
调用此函数,这里我们使用async await,使代码更简单易读,它将返回一个promise。
答案 2 :(得分:0)
如果您在python中遇到错误,则应验证有效载荷(您要发送到python后端的载荷)是正确的。 Javascript部分本身并没有多大用处。
但是,通过避免在重定向后执行其他操作并尝试使用putLabel
而不是顺序地并行地对Promise.all
进行后续调用,可以对代码进行一些改进,这就是您要做的如果您一个接一个地使用多个await
呼叫,则会得到
defaultHttpClient.post('/v1/projects', payload).then(response => {
// according to your code, in all calls of `putLabel`
// you're using the first response which you receive from the
// `/v1/projects` endpoint
Promise.all([
putLabel(0, response, this.newLabel, this.copiedLabels, this.labels),
putLabel(1, response, this.newLabel, this.copiedLabels, this.labels),
putLabel(2, response, this.newLabel, this.copiedLabels, this.labels)
]).then(() => {
// all promises have finished so we can redirect
window.location = `/projects/${response.data.id}/docs/create`;
})
})
答案 3 :(得分:0)
似乎您具有阻止编程语言的背景,但是ID
---
1
2
2
3
3
3
4
4
4
4
是JS
,这意味着您的代码不会自上而下执行除非,它位于{{1} }在进行任何异步函数调用之前使用non-blocking
函数(处理具有阻塞语言背景的非阻塞的最佳方法)。
不幸的是,这在函数外部不起作用,因此您需要将API调用放入函数主体中。据我所知,您可以将计数器抽象为for循环,这样:
async
但是通过这种方式,您的API调用将按顺序运行,这意味着总的函数调用时间是所有调用的总和,但是如果您不需要下一个调用中上一个调用的响应,则可以使用{{1} },由其他人建议。这样,您的函数调用时间与最长的API调用(所有调用同时完成)一样长,因此:
await
使用async function apiCalls(max = 2) {
let response = await defaultHttpClient.post('/v1/projects', payload)
window.location = `/projects/${response.data.id}/docs/create`
for (let i = 0; i <= max; i++) {
response = await putLabel(i, response, this.newLabel, this.copiedLabels, this.labels)
}
}
可以在Promise.all
函数内捕获并抛出/抛出错误(在您的情况下建议使用)。