How to return values ​​from asynchronous functions using async expect a callback function?

I am new to nodejs and it is back hell, I read about asynchronous / waiting for an introduction in node 8 and was interested to implement it this way

I have a specific set of methods that I need to call synchronously one after another for the trello API for example

  • create a panel.
  • create shortcuts using board ID
  • create cards using board ID
  • attach shortcuts to the map
  • create list in card
  • add each item to the list on the map

you can imagine in nodejs, this requires significant callbacks nested in each other to access the previous object

createProjectBoard: function (project) { t.post("1/board", { name: project.name, desc: project.description, defaultLists: false }, function (err, board) { if (err) { console.log(err); throw err; } //get board id from data let boardId = board.id let backlogListId = ""; let highId = "", mediumId = "", lowId = ""; //create labels t.post("1/labels", { name: 'High', color: 'red', idBoard: boardId }, function (err, label) { console.log(err || 'High label created'); if (err) return; highId = label.id; }); t.post("1/labels", { name: 'Medium', color: 'orange', idBoard: boardId }, function (err, label) { console.log(err || 'Medium label created'); if (err) return; mediumId = label.id; }); t.post("1/labels", { name: 'Low', color: 'yellow', idBoard: boardId }, function (err, label) { console.log(err || 'Low label created'); if (err) return; lowId = label.id; }); //create rest of the lists t.post("1/lists", { name: "Completed", idBoard: boardId }, function (e, l) { if (e) { console.log(e); return; } console.log(l); t.post("1/lists", { name: "Testing", idBoard: boardId }, function (e, l) { if (e) { console.log(e); return; } console.log(l); t.post("1/lists", { name: "In Progress", idBoard: boardId }, function (e, l) { if (e) { console.log(e); return; } console.log(l); //create backlog list t.post("1/lists", { name: "Backlog", idBoard: boardId }, function (e, list) { if (e) { console.log(e); return; } console.log(list); backlogListId = list.id; console.log("backlog card list id:" + backlogListId); _.each(project.userStories, function (story) { //assign labels let labelId = ""; switch (story.complexity.toLowerCase()) { case 'high': labelId = highId; break; case 'medium': labelId = mediumId; break; default: labelId = lowId; } t.post("1/cards", { name: story.title, idLabels: labelId, idList: backlogListId }, function (e, card) { if (e) { console.log(e); return; } let cardId = card.id; console.log("created id:" + cardId + ";card:" + story.title); t.post("1/cards/" + cardId + "/checklists", { name: "Acceptance Criteria" }, function (e, checklist) { if (e) { console.log(e); return; } console.log('checklist created:'); var clId = checklist.id; _.each(story.criterion, function (criteria) { t.post("1/cards/" + cardId + "/checklist/" + clId + "/checkItem", { name: criteria }, function (e, checkItem) { if (e) { console.log(e); return; } console.log('created check item:' + checkItem); }); }); }); }); }); }); }); }); }); }); } 

I'm still having problems with the code above where __ is involved. every loop, it calls asynchronously all the functions in the loop (reordering the order of the elements they should have been in initially) - so I thought that there should be a better way to make calls synchronously

I am interested in using await / async to clear the code, but having run into some problems when returning an object from an asynchronous callback

the solution is based on sails.js, the following is an excerpt from the TrelloService that I am writing

consider the following:

  createProjectBoard: async function(project) { //get board id from data let board; let boardId = ""; let backlogListId = ""; let highId = "", mediumId = "", lowId = ""; try { await t.post("1/board", { name: project.name, desc: project.description, defaultLists: false }, function(err, b) { if (err) { console.log(err); throw err; } console.log("board" + b); board = b; }); //create labels await t.post("1/labels", { name: 'High', color: 'red', idBoard: board.id }, function(err, label) { console.log(err || 'High label created'); if (err) return; highId = label.id; }); } catch (err) { console.log(err); } } 

I need the board value to be available in the label request call, so far I can’t get the board object, event, although I set the pending keywords

I need to be able to get objects from callback functions and use them in subsequent function calls synchronously

I use trllo api wrapper node -trello to make calls (t)

One way is to wrap the above with more callback functions as follows, but I don't think it would be best practice, since I would have to write wrapper callbacks for every object I need to use

 function foo(url,options,cb){ await t.post(url, options, function(err, b) { if (err) { console.log(err); throw err; } console.log("board" + b); cb(b); }); } var url = "1/board"; var options = { name: project.name, desc: project.description, defaultLists: false }; foo(url,options,function(board){ console.log(board); //board object }); 

any suggestions are welcome

+5
source share
2 answers

I am interested in using await / async to clear code

There are two steps to this: promisification and async. Your code gets confused because it skips the first step.

Promisification creates very simple promising wrapper functions around callback functions. For example, if t is an instance of the Trello class:

 Trello.prototype.postAsync = (url, data) => new Promise((resolve, reject) => { this.post(url, data, (err, result) => { if (err) { reject(err); } else { resolve(result); } }); }); 

The second step is to write the async / await logic using the return functions, not the callbacks. Since they promise a return, they code in a much more natural way:

 const board = await t.postAsync("1/board", { name: project.name, desc: project.description, defaultLists: false }); console.log("board" + board); //create labels let highId; try { highId = await t.postAsync("1/labels", { name: 'High', color: 'red', idBoard: board.id }); } catch (err) { console.log(err || 'High label created'); return; } 

The promise step is tedious and repetitive. There are several libraries that can automate call-to-promises, most notably Bluebird .

+5
source

await can only be used inside an asynchronous function, it was expecting the promise to be resolved, not what you want.

To clear your code, take a look at Promises a bit, but don't expect this to make your code less ugly, you just change the callback addon to "that" hell.

+1
source

Source: https://habr.com/ru/post/1270271/


All Articles