调用 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 + '&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 })

          })
      }
   }

//获取

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 = upLinktasks[taskId].downLink = downLink

没有迭代,没有阻塞,没有问题。

另外,这个数据结构会让getIndexOfTaskById过时!因为您已经拥有访问该任务所需的密钥!万岁!

如果您想知道如何迭代 tasks 结构为这样的地图 see here