如何在 Node.js 中使用 Promises 并与 Smartsheet 交互

How do I use Promises in Node.js and interacting with Smartsheet

请温柔点!新手试一试。我正在使用 node.js(第一次)

我有一个很大的(10,000 行)XML 文件,我需要翻阅它并在智能表中的 50 列中生成大约 900 行。我需要保留来自 XML 文件的顺序(重要)。

我的代码可以读取 xml 文件,并且可以写入 rows/columns 但显然我生成更新输入的速度比 smartsheet 可以处理的速度快,所以我尝试了 promises .我似乎无法破解它,非常感谢您能提供的任何帮助。系统生成所有记录,但在尝试将它们写入 smasrtsheet 时出现阻塞,并且订单已全部填满。

很高兴有人告诉我我找错了树,如果你能提出更好的方法。

提前致谢。

杰吉。

3 个代码块:

  1. testing.js 文件(脚本本身)

  2. testing.xml(xml 文件的精简版)

  3. testing.xsd(xml 架构文件)。

  4. testing.js


 // Initialize the client
var client = require('smartsheet');
var smartsheetClient = client.createClient({
  accessToken: '<insert your own access token before you run>', // use your access code
  logLevel: 'info'
});

 var fs= require('fs'),
 xml2js = require('xml2js');
 const parser = new xml2js.Parser();
 const xpath = require('xpath'),
 dom = require('xmldom').DOMParser;
 fs.readFile('testing.xml',function(err , data){
    var doc = new dom().parseFromString(data.toString(), 'text/xml');
    var select = xpath.useNamespaces('testing.xsd');
     if(err){
     //display error
     }
     else{
         for (var i=0; i < 10 ; i++ ){
            var rowcounter=i+1;
            var identifier = select('//Identifier/text()', doc)[i].nodeValue;
            var revision = select('//Revision/text()', doc)[i].nodeValue;
            var updated = select('//Updated/text()', doc)[i].nodeValue;
            var description = select('//Description/text()', doc)[i].nodeValue;
            var row = [{
                "toBottom": true,
                "cells": [
                // Note that the column Ids here are samples.  Adjust as required.
                {"columnId": 2461535086897028, "value": rowcounter, "strict": false},
                {"columnId": 6965134714267524, "value": identifier, "strict": false},
                {"columnId": 1335635180054404, "value": description, "strict": false},
                {"columnId": 7457715923511172, "value": revision, "strict": false},
                {"columnId": 1828216389298052, "value": updated, "strict": false},
                {"columnId": 7176240946800516, "value": 'Marker', "strict": false},
                ]
            }];
        writeRow(row); 
        sleep(); 
        }
    }
);

// DUMMY SLEEP FUNCTION
var sleep = function () {
  let now = Date.now(), end = now + 3000;
  while (now < end) { now = Date.now(); }
};

// Function to write row to sheet.
function writeRow(row) {
                    var options = {
                  sheetId: <insert your own sheet ID here>, //note real sheet id needed 
                  body: row
                  };
    return new Promise((resolve, reject) => {
        try {
            let obj = smartsheetClient.sheets.addRows(options);
            resolve(obj);
        } catch (err) {
            reject(err);
        };
    });
let myPromise = smartsheetClient.sheets.addRows(options);
myPromise.then(data => {
    console.log("Line Written :", data);
}).catch(err => {
    console.log(err);
});
}

  1. testing.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--  June 2021  -->
<DOCUMENT>
    <ITEM>
        <Identifier>2021-91</Identifier>
        <Revision>5</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item Description 1.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2021-97</Identifier>
        <Revision>1</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 2.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2020-14</Identifier>
        <Revision>0</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 3.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2019-44</Identifier>
        <Revision>2</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 4.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2021-06</Identifier>
        <Revision>2</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 5.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2019-13</Identifier>
        <Revision>2</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 6.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2020-03</Identifier>
        <Revision>2</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 7.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2021-19</Identifier>
        <Revision>2</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 8.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2019-56</Identifier>
        <Revision>0</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 9.</Description>
    </ITEM>
    <ITEM>
        <Identifier>2020-15</Identifier>
        <Revision>3</Revision>
        <Updated>Oct-20</Updated>
        <Description>Item description 10.</Description>
    </ITEM>
</DOCUMENT><?xml version="1.0" encoding="UTF-8" standalone="yes"?>

  1. testing.xsd

<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="DOCUMENT">
        <xs:complexType>
            <xs:sequence>
                <xs:element maxOccurs="unbounded" name="ITEM">
                    <xs:complexType>
                        <xs:sequence>
                            <xs:element name="Identifier" type="xs:unsignedShort" />
                            <xs:element name="Revision" type="xs:unsignedByte" />
                            <xs:element name="Updated" type="xs:string" />
                            <xs:element name="Description" type="xs:string" />
                        </xs:sequence>
                    </xs:complexType>
                </xs:element>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>

如有任何建议,我们将不胜感激。

问题


Promise 是异步的 API,它有自己独立的上下文。 它有3个状态,分别是pending、resolve和reject。

当 Promise 被 resolved 时,它调用 .then(cb) 并且如果失败,即 reject,它在内部调用 .catch(cb)。

首先,无论是解决还是拒绝,您都没有等待 Promise 完成。

您应该使用 .then() 和 .catch() 来等待它完成。也许 async/await API 会更好。

解决方案


实现延迟功能的标准方式


const delay = ms => new Promise(resolve => setTimeout(() => resolve(), ms)

writeRow()


 function writeRow(row) {//Return your promise and let it be controlled outside of function
            var options = {
                sheetId: < insert your own sheet ID here > , //note real sheet id needed 
                body: row
            };
            return new Promise((resolve, reject) => {
                try {
                    let obj = smartsheetClient.sheets.addRows(options);
                    resolve(obj);
                } catch (err) {
                    reject(err);
                };
            });
}

runner : 将您的逻辑包装到异步函数中以使用 await API.


(或者您可以使用传统方式通过 .then()、.catch() 来控制 promise)

async function runner(){
    ...your scripts...
    for (var i = 0; i < 10; i++) {
       ...
       await writeRow(row)
       await sleep(3000)//write row and wait for 3 seconds
       ...
    }
}


...your scripts...
}

runner()

你必须知道

  1. Smartsheet API 不支持对给定令牌的同时调用。
  2. 智能表API 一次调用可以 insert/update 多行,比如 100 行 一个电话。

所以改变你的解决方案的结构:

  1. 阅读您的源代码并将智能表行列表构建到 insert/update。
  2. 每 100 行块拆分该行列表。
  3. Insert/update 每 100 行