简体   繁体   English

在JavaScript / Node.js中,如何使用Async / Await

[英]In JavaScript/Node.js, how to use Async/Await

In JavaScript/Node.js, how to use Async/Await for the below code to return placeName with a,b,c & d. 在JavaScript / Node.js中,如何对下面的代码使用Async / Await来返回带有a,b,c和d的placeName。

test.csv is having c,d test.csv有c,d

var placeName = ["a","b"];
var csvFile = 'test.csv';
fs.readFile(csvFile, 'UTF-8', function(err, csv) {
  $.csv.toArrays(csv, {}, function(err, data) {
    for(var i=0, len=data.length; i<len; i++) {
      console.log(data[i]); //Will print every csv line as a newline
      placeName.push(data[i][0].toString());
    }
  });
   console.log(placeName); //Inside the function the array show a,b,c,d
});

// Prints only a and b. Did not add c & d from the csv.
console.log(placeName); 

Create a function returning a promise 创建一个返回承诺的函数

The await operator waits for a promise to be fulfilled and can only be used within async functions - which return a promise when called. await操作符等待诺言被兑现,并且只能在async函数中使用-调用时返回诺言。 So updating place names will need to be written as a function that returns a promise. 因此,更新地名将需要编写为返回诺言的函数。 Using a single promise for all operations is possible but not recommended: 可以对所有操作使用一个promise,但不建议这样做:

function addNames(placeName, csvFile) {
    return new Promise( (resolve, reject) => {
        fs.readFile(csvFile, 'UTF-8', function(err, csv) {
            if(err) {
               reject(err);
            }
            else {
                $.csv.toArrays(csv, {}, function(err, data) {
                    if( err) {
                        reject( err);
                    }
                    else {
                        for(var i=0, len=data.length; i<len; i++) {
                            console.log(data[i]); //print supplied data elements
                            placeName.push(data[i][0].toString());
                        }
                    }
                    resolve( placeName);
                });

            }
        });
    });
}

Although untested, this is based on the posted code: the input placeName array is modified in place. 尽管未经测试,但这是基于发布的代码的:输入的placeName数组已就地修改。 If fulfilled, the promise value is set to the modified array. 如果满足,则将promise值设置为修改后的数组。 However .... 但是..

Reducing indented code 减少缩进代码

Notice the code becomes more indented the more node style callback operations are added? 注意,添加了更多节点样式的回调操作后,代码变得更加缩进? Taken to extreme this can result in a condition known as "call back hell" - difficult to write, compile without error or maintain. 极端地讲,这可能导致一种称为“回调地狱”的情况-难以编写,无法正确编译或维护。

Removing nested callbacks is one of the design aims of promises and can be achieved by promisifying operations separately. 删除嵌套的回调是Promise的设计目标之一,可以通过分别使操作分散来实现。 The following example separates not just reading and decoding, but transforming the decoded data and adding it to an existing array: 下面的示例不仅分离读取和解码,还转换解码后的数据并将其添加到现有数组中:

function readCsvFile( csvFile) {
    return new Promise( (resolve, reject)  => {
        fs.readFile(csvFile, 'UTF-8',
           (err, csv) => err ? reject(err) : resolve( csv)
        );
    });
}
function decodeCsv( csv) {
    return new Promise( (resolve, reject) => {
        $.csv.toArrays(csv, {},
           (err, data) => err ? reject( err) : resolve( data)
        );
    });
}
function extractNames( data) {
   return data.map( item => item[0].toString());
}

function addNames( placeName, csvFile) {
    return readCsvFile( csvFile)
    .then(decodeCsv)
    .then(extractNames)
    .then(  // push new names to placeName and return placeName
       names => names.reduce( (a,name) => {a.push(name);return a}, placeName)
     );
}

Calling as part of a promise chain 作为承诺链的一部分进行呼叫

Usage without using async/await requires adding promise handlers for fulfillment and rejection to be called asynchronously after data becomes available or an error occurs: 不使用异步/等待的用法需要在数据可用或发生错误后异步添加承诺处理程序以实现实现和拒绝。

var placeName = ["a","b"];
var csvFile = 'test.csv';

addNames( placeName, csvFile)
.then( placeName => console.log(placeName)) // log updated places
.catch( err => console.log( err));  // or log the error.

Usage of await await用法

As mentioned, the await operator can only be used inside async functions. 如前所述, await运算符只能在异步函数内部使用。 It waits for fulfilled promise data so that it can be processed further inside the same function. 它等待已实现的承诺数据,以便可以在同一功能内对其进行进一步处理。

async function example() {

    var placeName = ["a","b"];
    var csvFile = 'test.csv';

    await addNames( placeName, csvFile);
    // do something with placeName

    return somethingElse;       
}

Adding fulfillment and rejection handlers to the promise returned by calling example has not been shown. 未显示将实现和拒绝处理程序添加到调用example返回的promise中。

About return await ... 关于return await ...

Note that a promise returned from an async function resolves the promise returned by calling the function. 请注意,从异步函数返回的承诺将解决通过调用该函数返回的承诺。 Hence the coding pattern of 因此,

 return await operand

contains an unnecessary await operator. 包含不必要的await运算符。

Writing async functions instead of ordinary ones (TLDR) 编写异步函数而不是普通函数(TLDR)

Using async functions in node still requires converting operations which use error/success callbacks into requests that returns a promise ("promisifying" the operation), but syntactically allows writing code processing the request to be written immediately following await operations. 在节点中使用async函数仍然需要将使用错误/成功回调的操作转换为返回承诺的请求(“使操作承诺”),但是从语法上允许编写处理请求的代码,该请求将在await操作之后立即写入。 Code produced is similar in style to procedural code. 生成的代码在样式上与过程代码相似。 For example: 例如:

function readCsvFile( csvFile) {
    return new Promise( (resolve, reject)  => {
        fs.readFile(csvFile, 'UTF-8',
           (err, csv) => err ? reject(err) : resolve( csv)
        );
    });
}
function decodeCsv( csv) {
    return new Promise( (resolve, reject) => {
        $.csv.toArrays(csv, {},
           (err, data) => err ? reject( err) : resolve( data)
        );
    });
}

async function addNames( placeName, csvFile) {
    let csv = await readCsvFile( csvFile);
    let arrays = await decodeCsv( csv);
    let names = arrays.map( item => item[0].toString());
    placeName.push.apply( placeName, names);
    return placeName;
}

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

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