質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1236閲覧

Node.jsでGoogleSpreadSheetと連携しようとした際にcallbackエラー

kotaro_nagano

総合スコア11

Google API

Googleは多種多様なAPIを提供していて、その多くはウェブ開発者向けのAPIです。それらのAPIは消費者に人気なGoogleのサービス(Google Maps, Google Earth, AdSense, Adwords, Google Apps,YouTube等)に基づいています。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/09/26 09:23

編集2019/09/27 01:20

前提・実現したいこと

コードのgetInfo関数で引数がコールバックになっているのですが、そこの部分でコールバックが存在しないというエラーが起こる

発生している問題・エラーメッセージ

/Users/user/dev/project/node_modules/google-spreadsheet/index.js:84 cb(); ^ TypeError: cb is not a function at /Users/user/dev/project/node_modules/google-spreadsheet/index.js:84:7 at /Users/user/dev/project/node_modules/google-spreadsheet/node_modules/google-auth-library/lib/auth/jwtclient.js:119:5 at /Users/user/dev/project/node_modules/google-spreadsheet/node_modules/google-auth-library/lib/auth/jwtclient.js:138:16 at Request._callback (/Users/user/dev/project/node_modules/google-spreadsheet/node_modules/gtoken/lib/index.js:228:14) at Request.self.callback (/Users/user/dev/project/node_modules/request/request.js:185:22) at Request.emit (events.js:197:13) at Request.<anonymous> (/Users/user/dev/project/node_modules/request/request.js:1161:10) at Request.emit (events.js:197:13) at IncomingMessage.<anonymous> (/Users/user/dev/project/node_modules/request/request.js:1083:12) at Object.onceWrapper (events.js:285:13)

js

1 /Users/user/dev/atom-tools/node_modules/google-spreadsheet/index.js 2 3 this.setAuthToken = function(auth_id) { 4 if (auth_mode == "anonymous") auth_mode = "token"; 5 setAuthAndDependencies(auth_id); 6 }; 7 8...中略 9 1075: function renewJwtAuth(cb) { 1176: auth_mode = "jwt"; 1277: jwt_client.authorize(function(err, token) { 1378: if (err) return cb(err); 1479: self.setAuthToken({ 1580: type: token.token_type, 1681: value: token.access_token, 1782: expires: token.expiry_date 1883: }); 1984: cb(); 2085: }); 2186: } 22 23・・・中略 24 25 function setAuthAndDependencies(auth) { 26 google_auth = auth; 27 if (!options.visibility) { 28 visibility = google_auth ? "private" : "public"; 29 } 30 if (!options.projection) { 31 projection = google_auth ? "full" : "values"; 32 } 33 } 34 35・・・中略 36 37 // public API methods 38 this.getInfo = function(cb) { 39 self.makeFeedRequest(["worksheets", ss_key], "GET", null, function( 40 err, 41 data 42 ) { 43 if (err) return cb(err); 44 if (data === true) { 45 return cb(new Error("No response to getInfo call")); 46 } 47 var ss_data = { 48 id: data.id, 49 title: data.title, 50 updated: data.updated, 51 author: data.author, 52 worksheets: [] 53 }; 54 var worksheets = forceArray(data.entry); 55 worksheets.forEach(function(ws_data) { 56 ss_data.worksheets.push(new SpreadsheetWorksheet(self, ws_data)); 57 }); 58 self.info = ss_data; 59 self.worksheets = ss_data.worksheets; 60 cb(null, ss_data); 61 }); 62 }; 63 64・・・中略 65 66 // This method is used internally to make all requests 67 this.makeFeedRequest = function(url_params, method, query_or_data, cb) { 68 var url; 69 var headers = {}; 70 if (!cb) cb = function() {}; 71 if (typeof url_params == "string") { 72 // used for edit / delete requests 73 url = url_params; 74 } else if (Array.isArray(url_params)) { 75 //used for get and post requets 76 url_params.push(visibility, projection); 77 url = GOOGLE_FEED_URL + url_params.join("/"); 78 } 79 80 async.series({ 81 auth: function(step) { 82 if (auth_mode != "jwt") return step(); 83 // check if jwt token is expired 84 if (google_auth && google_auth.expires > +new Date()) return step(); 85 renewJwtAuth(step); 86 }, 87 request: function(result, step) { 88 if (google_auth) { 89 if (google_auth.type === "Bearer") { 90 headers["Authorization"] = "Bearer " + google_auth.value; 91 } else { 92 headers["Authorization"] = "GoogleLogin auth=" + google_auth; 93 } 94 } 95 96 headers["Gdata-Version"] = "3.0"; 97 98 if (method == "POST" || method == "PUT") { 99 headers["content-type"] = "application/atom+xml"; 100 } 101 102 if ( 103 method == "PUT" || 104 (method == "POST" && url.indexOf("/batch") != -1) 105 ) { 106 headers["If-Match"] = "*"; 107 } 108 109 if (method == "GET" && query_or_data) { 110 var query = "?" + querystring.stringify(query_or_data); 111 // replacements are needed for using structured queries on getRows 112 query = query.replace(/%3E/g, ">"); 113 query = query.replace(/%3D/g, "="); 114 query = query.replace(/%3C/g, "<"); 115 url += query; 116 } 117 118 request( 119 { 120 url: url, 121 method: method, 122 headers: headers, 123 gzip: options.gzip !== undefined ? options.gzip : true, 124 body: method == "POST" || method == "PUT" ? query_or_data : null 125 }, 126 function(err, response, body) { 127 if (err) { 128 return cb(err); 129 } else if (response.statusCode === 401) { 130 return cb(new Error("Invalid authorization key.")); 131 } else if (response.statusCode >= 400) { 132 var message = _.isObject(body) 133 ? JSON.stringify(body) 134 : body.replace(/&quot;/g, '"'); 135 return cb( 136 new Error( 137 "HTTP error " + 138 response.statusCode + 139 " (" + 140 http.STATUS_CODES[response.statusCode] 141 ) + 142 ") - " + 143 message 144 ); 145 } else if ( 146 response.statusCode === 200 && 147 response.headers["content-type"].indexOf("text/html") >= 0 148 ) { 149 return cb( 150 new Error( 151 "Sheet is private. Use authentication or make public. (see https://github.com/theoephraim/node-google-spreadsheet#a-note-on-authentication for details)" 152 ) 153 ); 154 } 155 156 if (body) { 157 var xml_parser = new xml2js.Parser({ 158 // options carried over from older version of xml2js 159 // might want to update how the code works, but for now this is fine 160 explicitArray: false, 161 explicitRoot: false 162 }); 163 xml_parser.parseString(body, function(err, result) { 164 if (err) { 165 xml_parser = null; 166 body = null; 167 return cb(err); 168 } 169 if (cb.length == 3) { 170 cb(null, result, body); 171 } else { 172 body = null; 173 cb(null, result); 174 } 175 }); 176 } else { 177 if (err) cb(err); 178 else cb(null, true); 179 } 180 } 181 ); 182 } 183 }); 184 };

該当のソースコード

js

1"use strict"; 2 3const googleSpreadSheet = require("google-spreadsheet"); 4 5const doc = new googleSpreadSheet( 6 "1X98eannyhE" 7); 8 9let sheet; 10 11const setAuth = () => 12 new Promise((resolve, reject) => { 13 const creds = require("./903c28f.json"); 14 doc.useServiceAccountAuth(creds, getInfoAndSheets()); 15 }); 16 17const getInfoAndSheets = () => 18 new Promise((resolve, reject) => { 19 doc.getInfo((err, info) => { 20 sheet = info.worksheets[0]; 21 }); 22 resolve(); 23 }); 24 25const workingWithCells = () => { 26 const COLUMS = { 27 name: 1, 28 price: 2 29 }; 30 sheet.getCells( 31 { 32 "min-row": 2, 33 "max-row": 5, 34 "return-empty": true 35 }, 36 (err, cells) => { 37 for (let i = 0; i < cells.length / sheet.colCount; i += 1) { 38 const name = cells[i * sheet.colCount + COLUMS.name].value; 39 const price = cells[i * sheet.colCount + COLUMS.price].value; 40 } 41 } 42 ); 43}; 44 45const a = async () => { 46 await setAuth(); 47 await workingWithCells(); 48}; 49 50const main = () => { 51 a(); 52}; 53 54main(); 55

試したこと

js

1const getInfoAndSheets = () => 2 new Promise((resolve, reject) => { 3 doc.getInfo((err, info) => { 4 sheet = info.worksheets[0]; 5 }); 6 resolve(); 7 });

上記の関数を下記に変更

const getInfoAndSheets = () => new Promise((resolve, reject) => { doc.getInfo((err, info) => { if(!info) info = function(){} sheet = info.worksheets[0]; }); resolve(); });

infoがないからエラーが起きているのかと思い、条件分岐を追加しましたが、あまり意味はなかったです。

補足

一応同じ症状の方が一人いたのですが、あまり解決策が出されていなかった
https://github.com/theoephraim/node-google-spreadsheet/issues/105

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mouse_484

2019/09/26 12:23

エラーのcb()の部分がコードに無いようです...
kotaro_nagano

2019/09/27 00:38

エラー側のcb()貼ります。
kotaro_nagano

2019/09/27 00:45

エラーのcb部分のコード貼りました。 よろしくお願いします。
mouse_484

2019/09/27 00:50

全体のコードをとうしての一貫性が理解できません コードすべてを貼っていただけませんか?
kotaro_nagano

2019/09/27 01:09

プラグイン側のコードが文字数制限で表示できないので、別途質問作ります。
kotaro_nagano

2019/09/27 01:17

該当プログラム部分だけ貼っておきました。
guest

回答1

0

自己解決

無事解決しました。

問題はモジュール側にあったみたいです。

https://scrapbox.io/shokai/Node.js%E3%81%A8async-await%E3%81%A7Google_Spreadsheet%E3%81%AB%E6%9B%B8%E3%81%8F

google-spreadsheet-as-promised npm https://www.npmjs.com/package/google-spreadsheet-as-promised これを使うのが良かった google-spreadsheet npm https://www.npmjs.com/package/google-spreadsheetをpromise化したやつなので、async-awaitで書ける

モジュール自体がasyncにしか対応していない書き方をしていたからPromiseやasync-awaitで書くことができなかった。

投稿2019/09/27 01:54

kotaro_nagano

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問