调用 API 作为非阻塞调用 JavaScript
Calling an API as a non-blocking call JavaScript
我正在构建一个类似于待办事项列表的功能,当在输入任务字段上按下 Enter 时,它会添加一个任务。 Enter 调用一个 API(添加任务),执行大约需要 200 毫秒。由于这是阻塞调用,它会阻碍我的代码完全执行并影响我系统的可用性。这是我想要实现的代码示例。
handleChange(事件){
if (e.key === 'Enter') {
targetTaskId = e.target.getAttribute("data-downlink")
this.props.addTask(this.props.currentProject.id, '', '', taskId, this.props.currentTasks) //this function calls an add Task API which halts my system momentarily
targetSelector = targetTaskId
$('#' + targetSelector).focus()
this.setState({activeTask: targetSelector})
highlightActiveComponent(targetTaskId)
}
}
//添加任务
export function addTask (project_id, taskName, taskNotes, upLink, taskList) {
console.log('Add Task API call', project_id, taskName, taskNotes, upLink)
return (dispatch) => {
callApi('tasks?projectId=' + project_id + '&name=' + taskName + '¬es=' + taskNotes + '&upLink=' + upLink, 'post')
.then(res => {
console.log('Response new task ', res)
let newTask = {name: res.name, id: res.id, notes: res.notes, upLink: upLink, projectId: project_id, assignee: 0, completed: 0, tags: [], isLiked: false, stories: [], likes: [], downLink: res.downLink}
let newTaskList = addTaskToTaskList(taskList, upLink, newTask)
dispatch(updateTasks({currentTasks: newTaskList}))
dispatch({ type: 'SET_ACTIVE_TASK_ID', payload: res.id })
})
}
}
//获取
export const API_URL = 'https://clients.rohan.axcelmedia.ca/v1'
export default function callApi (endpoint, method = 'get', body) {
let headers = {
'Accept': 'application/json',
'Content-Type' : 'application/json'
}
if (auth.loggedIn()) {
headers = _.merge(headers, {
Authorization: `Bearer ${auth.getToken()}`
})
}
return fetch(`${API_URL}/${endpoint}`, {
headers,
method,
body: JSON.stringify(body)
}).then(response => {
return response
}).then(response => response.json().then(json => ({ json, response })))
.then(({ json, response }) => {
if (!response.ok) {
return Promise.reject(json)
}
return json
})
.then(
response => response,
error => error
)
}
将任务添加到任务列表
export function addTaskToTaskList(tasks, upLink, newTask){
updateTaskDownLink(tasks, newTask.upLink, newTask.id)
updateTaskUpLink(tasks, newTask.downLink, newTask.id)
if(upLink == 0){
tasks.unshift(newTask)
// console.log("Added in the start", tasks)
return JSON.parse(JSON.stringify(tasks))
}
let myIndex = getIndexOfTaskById(tasks, upLink)
console.log("Added the new task from helper", myIndex)
if (myIndex) {
console.log("Added the new task")
tasks.splice(myIndex + 1, 0, newTask);
// console.log("New Task List", JSON.parse(JSON.stringify(tasks)))
}
return JSON.parse(JSON.stringify(tasks))
}
export function updateTaskUpLink(tasks, taskId, upLink){
tasks.forEach(function(element, index) {
if(element.id == taskId) { element.upLink = upLink }
});
return tasks
}
export function updateTaskDownLink(tasks, taskId, downLink){
tasks.forEach(function(element, index) {
if(element.id == taskId) { element.downLink = downLink }
});
return tasks
}
我的问题是,是否可以以非阻塞方式调用此 API,以便我的代码继续执行,并且当收到 api 的响应时,我的光标移动到以无缝的方式完成新任务。
任何帮助,将不胜感激。谢谢
[编辑]:添加了提取函数来演示异步调用
您应该使用 Fetch API 之类的东西以非阻塞方式调用 API:
fetch("/api/v1/endpoint/5/", {
method: "get",
credentials: "same-origin",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}
}).then(function(response) {
return response.json();
}).then(function(data) {
console.log("Data is ok", data);
}).catch(function(ex) {
console.log("parsing failed", ex);
});
console.log("Ciao!");
代码段中显示数据的代码只有在服务器返回一些数据时才会执行。
这意味着在我的示例中日志 "Ciao!" 将在 "Data is ok: ..."
之前显示
希望这对您有所帮助:)
该片段的学分:https://gist.github.com/marteinn/3785ff3c1a3745ae955c
首先,return JSON.parse(JSON.stringify(tasks))
是多余的,您可以直接 return tasks
,这可能会单独解决您的速度问题。但以防万一。
您的代码可能由于此处的此类问题而被阻塞
tasks.forEach(function(element, index) {
if(element.id == taskId) { element.upLink = upLink }
});
return tasks
您为 updateTaskDownLink
遍历 tasks
数组,为 updateTaskUpLink
再次遍历,可能为 getIndexOfTaskById
再次遍历,这是很多不必要的迭代。
与其一遍又一遍地搜索一系列任务,不如在地图中构建任务
tasks = {
"someTaskId": {
id: "someTaskId",
upLink: "uplink stuff",
downLink: "downlink stuff"
}
}
这样当你去更新任务的时候真的很简单也很快速
tasks[taskId].upLink = upLink
或 tasks[taskId].downLink = downLink
没有迭代,没有阻塞,没有问题。
另外,这个数据结构会让getIndexOfTaskById
过时!因为您已经拥有访问该任务所需的密钥!万岁!
如果您想知道如何迭代 tasks
结构为这样的地图 see here
我正在构建一个类似于待办事项列表的功能,当在输入任务字段上按下 Enter 时,它会添加一个任务。 Enter 调用一个 API(添加任务),执行大约需要 200 毫秒。由于这是阻塞调用,它会阻碍我的代码完全执行并影响我系统的可用性。这是我想要实现的代码示例。
handleChange(事件){
if (e.key === 'Enter') {
targetTaskId = e.target.getAttribute("data-downlink")
this.props.addTask(this.props.currentProject.id, '', '', taskId, this.props.currentTasks) //this function calls an add Task API which halts my system momentarily
targetSelector = targetTaskId
$('#' + targetSelector).focus()
this.setState({activeTask: targetSelector})
highlightActiveComponent(targetTaskId)
}
}
//添加任务
export function addTask (project_id, taskName, taskNotes, upLink, taskList) {
console.log('Add Task API call', project_id, taskName, taskNotes, upLink)
return (dispatch) => {
callApi('tasks?projectId=' + project_id + '&name=' + taskName + '¬es=' + taskNotes + '&upLink=' + upLink, 'post')
.then(res => {
console.log('Response new task ', res)
let newTask = {name: res.name, id: res.id, notes: res.notes, upLink: upLink, projectId: project_id, assignee: 0, completed: 0, tags: [], isLiked: false, stories: [], likes: [], downLink: res.downLink}
let newTaskList = addTaskToTaskList(taskList, upLink, newTask)
dispatch(updateTasks({currentTasks: newTaskList}))
dispatch({ type: 'SET_ACTIVE_TASK_ID', payload: res.id })
})
}
}
//获取
export const API_URL = 'https://clients.rohan.axcelmedia.ca/v1'
export default function callApi (endpoint, method = 'get', body) {
let headers = {
'Accept': 'application/json',
'Content-Type' : 'application/json'
}
if (auth.loggedIn()) {
headers = _.merge(headers, {
Authorization: `Bearer ${auth.getToken()}`
})
}
return fetch(`${API_URL}/${endpoint}`, {
headers,
method,
body: JSON.stringify(body)
}).then(response => {
return response
}).then(response => response.json().then(json => ({ json, response })))
.then(({ json, response }) => {
if (!response.ok) {
return Promise.reject(json)
}
return json
})
.then(
response => response,
error => error
)
}
将任务添加到任务列表
export function addTaskToTaskList(tasks, upLink, newTask){
updateTaskDownLink(tasks, newTask.upLink, newTask.id)
updateTaskUpLink(tasks, newTask.downLink, newTask.id)
if(upLink == 0){
tasks.unshift(newTask)
// console.log("Added in the start", tasks)
return JSON.parse(JSON.stringify(tasks))
}
let myIndex = getIndexOfTaskById(tasks, upLink)
console.log("Added the new task from helper", myIndex)
if (myIndex) {
console.log("Added the new task")
tasks.splice(myIndex + 1, 0, newTask);
// console.log("New Task List", JSON.parse(JSON.stringify(tasks)))
}
return JSON.parse(JSON.stringify(tasks))
}
export function updateTaskUpLink(tasks, taskId, upLink){
tasks.forEach(function(element, index) {
if(element.id == taskId) { element.upLink = upLink }
});
return tasks
}
export function updateTaskDownLink(tasks, taskId, downLink){
tasks.forEach(function(element, index) {
if(element.id == taskId) { element.downLink = downLink }
});
return tasks
}
我的问题是,是否可以以非阻塞方式调用此 API,以便我的代码继续执行,并且当收到 api 的响应时,我的光标移动到以无缝的方式完成新任务。 任何帮助,将不胜感激。谢谢 [编辑]:添加了提取函数来演示异步调用
您应该使用 Fetch API 之类的东西以非阻塞方式调用 API:
fetch("/api/v1/endpoint/5/", {
method: "get",
credentials: "same-origin",
headers: {
"Accept": "application/json",
"Content-Type": "application/json"
}
}).then(function(response) {
return response.json();
}).then(function(data) {
console.log("Data is ok", data);
}).catch(function(ex) {
console.log("parsing failed", ex);
});
console.log("Ciao!");
代码段中显示数据的代码只有在服务器返回一些数据时才会执行。
这意味着在我的示例中日志 "Ciao!" 将在 "Data is ok: ..."
之前显示希望这对您有所帮助:)
该片段的学分:https://gist.github.com/marteinn/3785ff3c1a3745ae955c
首先,return JSON.parse(JSON.stringify(tasks))
是多余的,您可以直接 return tasks
,这可能会单独解决您的速度问题。但以防万一。
您的代码可能由于此处的此类问题而被阻塞
tasks.forEach(function(element, index) {
if(element.id == taskId) { element.upLink = upLink }
});
return tasks
您为 updateTaskDownLink
遍历 tasks
数组,为 updateTaskUpLink
再次遍历,可能为 getIndexOfTaskById
再次遍历,这是很多不必要的迭代。
与其一遍又一遍地搜索一系列任务,不如在地图中构建任务
tasks = {
"someTaskId": {
id: "someTaskId",
upLink: "uplink stuff",
downLink: "downlink stuff"
}
}
这样当你去更新任务的时候真的很简单也很快速
tasks[taskId].upLink = upLink
或 tasks[taskId].downLink = downLink
没有迭代,没有阻塞,没有问题。
另外,这个数据结构会让getIndexOfTaskById
过时!因为您已经拥有访问该任务所需的密钥!万岁!
如果您想知道如何迭代 tasks
结构为这样的地图 see here