简体   繁体   English

调用API作为非阻塞调用JavaScript

[英]Calling an API as a non-blocking call JavaScript

I am building a todo-list like feature which adds a task when Enter is pressed on an input task field. 我正在构建类似待办事项列表的功能,当在输入任务字段上按Enter键时可以添加任务。 The Enter calls an API (add Task) which takes approx 200ms to execute. Enter调用一个API(添加任务)大约需要200毫秒的时间来执行。 Since this is blocking call it hinders my code to execute fully and affects the usability of my system. 由于这阻塞了调用,因此妨碍了我的代码完全执行并影响了系统的可用性。 Here is a code example of what I am trying to achieve. 这是我要实现的代码示例。

handleChange (event) { 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)

   } 

} }

//addTask // addTask

   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 + '&notes=' + 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 })

          })
      }
   }

//Fetch //取

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
    )
}

Add Task to tasklist 将任务添加到任务列表

    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
    }

My question is, is there anyway to call this API in a non-blocking fashion so that my code continues to execute and when the response from the api is received my cursor moves to the new task in a seamless manner. 我的问题是,是否仍然可以以非阻塞方式调用此API,以便我的代码继续执行,并且在收到api的响应后,我的光标将以无缝方式移动到新任务。 Any help would be appreciated. 任何帮助,将不胜感激。 Thankyou [EDIT] : Added fetch function to demonstrate the async calls 谢谢[编辑]:添加了提取功能以演示异步调用

You should use something like Fetch API for call the API in a non-blocking way: 您应该使用类似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!"); 

The code that shows data in the snippet will be executed only when some data is returned by the server. 仅当服务器返回某些数据时,才会执行显示摘录中数据的代码。

This means that in my example the log "Ciao!" 这意味着在我的示例中,日志为“ Ciao!”。 will be showed before "Data is ok: ..." 将在“数据正常:...”之前显示

Hope this helps :) 希望这可以帮助 :)

credits for the snippet: https://gist.github.com/marteinn/3785ff3c1a3745ae955c 摘录的内容: https : //gist.github.com/marteinn/3785ff3c1a3745ae955c

First of all return JSON.parse(JSON.stringify(tasks)) is redundant, you can just return tasks right there, that will probably fix your speed problem alone. 首先return JSON.parse(JSON.stringify(tasks))是多余的,您可以仅在此处return tasks ,这可能会单独解决速度问题。 But incase it doesn't. 但是万一没有。

Your code might be blocking due to this type of thing here 您的代码可能由于这种情况而被阻止

tasks.forEach(function(element, index) {
  if(element.id == taskId) { element.upLink = upLink }
});

return tasks

You iterate over the tasks array for updateTaskDownLink , again for updateTaskUpLink and probably again for getIndexOfTaskById , this is a lot of needless iteration. 您遍历tasks数组updateTaskDownLink ,再次updateTaskUpLink ,可能再次getIndexOfTaskById ,这是很多不必要的迭代。

Instead of searching through an array of tasks over and over, you should structure your tasks in a map 而不是一遍又一遍地搜索一系列任务,您应该在地图中构造任务

tasks = {
  "someTaskId": {
    id: "someTaskId",
    upLink: "uplink stuff",
    downLink: "downlink stuff"
  }
}

This way when you go to update the task its really simple and really fast 这样,当您去更新任务时,它非常简单,非常快

tasks[taskId].upLink = upLink or tasks[taskId].downLink = downLink tasks[taskId].upLink = upLinktasks[taskId].downLink = downLink

No iterating, no blocking, no problem. 没有迭代,没有阻塞,没有问题。

Also, this data structure will make getIndexOfTaskById obsolete! 同样,此数据结构将使getIndexOfTaskById变得过时! because you already have the key needed to access that task! 因为您已经拥有访问该任务所需的密钥! Hooray! 万岁!

If you're wondering how to iterate over your tasks structured as a map like that see here 如果您想知道如何遍历像这样的地图结构化的tasks请参见此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM