简答
这不是错误,这实际上是返回的值 - 一个未决的承诺。 Read this 了解什么是承诺。您会看到这一点,因为在您记录该值时,该值还不存在 - 仍在获取 CSV 数据。
为了立即解决您的问题,您需要更改它...
console.log(getItem(BUCKET, FILE))
...到这个:
return getItem(BUCKET, FILE).then((data) => {
console.log(data)
})
这会将 Promise 返回给 IBM 云,以便它可以等待操作完成,并且仅在返回数据后才执行您的 console.log 语句,而不是立即执行。
此外,您还需要添加这个...
return data
...在您的 then 调用内的回调结束时(在您的 if (data !== null) 块下方) - 否则您现在只能在外面看到 undefined。
长答案
Promise {pending} 不是错误。这是getItem 函数的返回值:一个未决的承诺。
如果你不知道关于他们的承诺是什么here。
简而言之,promise 表示异步完成的操作。在你 console.log-ing 承诺的那一刻,它甚至还没有值,因为 CSV 提取操作仍在进行中。
如果 Promise 起作用,显示操作执行顺序的简短示例:
// Let's assume that the function delay(s) returns a promise that
// resolves only after the given amount of seconds has elapsed
console.log('A')
delay(1).then(function () {
console.log('B')
return delay(2)
}).then(function () {
console.log('C')
})
console.log('D')
// Output will be:
// (immediately)
// A
// D <<<<< !!!!!!!
// (1 second later)
// B
// (2 seconds later)
// C
为了说明正在发生的事情,让我将代码简化为在您看到此日志输出之前发生的部分:
function getItem (bucketName, itemName) {
console.log(`Retrieving item from bucket: ${bucketName}, key:${itemName}`)
return somePromise
}
console.log(getItem(BUCKET, FILE))
当然,somePromise 在你的代码中并不作为变量存在,但我这里用它来表示cos.getObject(...).promise() 的返回值,这是一个承诺。
因此,在代码的初始执行中,您会看到Retrieveing item from bucket,然后是返回值,即待处理的承诺。这与您描述的相符。
但是,此时您的代码尚未完成。获取操作仅已启动,尚未完成。完成后,then 或 catch 处理程序中的代码也将运行!所以,我希望一秒钟后您还会在输出中看到File Contents:... 和hellllllo 或ERROR:...。 (如果您不这样做,那么您的执行环境可能不支持异步任务或执行时间限制太短。)
如果您稍后确实看到了输出,但不确定如何在进一步的代码中使用获取的值:一旦有任何异步组件,使用该组件的所有代码本身都必须是异步的。这意味着,您不能简单地 return 中的值 main 例如,您还必须从 main 返回一个承诺,并且使用 main 的外部代码也必须知道如何处理承诺,等等。幸运的是,IBM 云确实支持异步响应,所以只要确保你也从 main 返回了一个承诺,例如使用return getItem(BUCKET, FILE)。
更好的解决方案
如果您使用 Node v8 附带的async/await syntax,代码的读写会变得更好。如果您选择正确的运行时,IBM 云允许使用节点 v8。在这种情况下,异步代码将简化为:
const COS = require('ibm-cos-sdk').S3
async function main (params) { // <<< async keyword added
const IAM_API_KEY = process.env.__OW_IAM_NAMESPACE_API_KEY
const ENDPOINT = 's3.eu-gb.cloud-object-storage.appdomain.cloud'
const BUCKET = 'my-bucket'
const FILE = 'Sample.csv'
const config = {
endpoint: ENDPOINT,
apiKeyId: IAM_API_KEY
}
const cos = new COS(config)
const options = {
Bucket: BUCKET
}
async function getItem (bucketName, itemName) { // <<< async keyword added
console.log(`Retrieving item from bucket: ${bucketName}, key:${itemName}`)
try {
const data = await cos.getObject({ // <<< turned into assignment with await
Bucket: bucketName,
Key: itemName
}).promise() // <<< no .then with callback needed
if (data != null) {
console.log('File Contents: ' + Buffer.from(data.Body).toString())
console.log('hellllllo')
}
return data
} catch (e) { // <<< turned into simple catch
console.error(`ERROR: ${e.code} - ${e.message}\n`)
}
}
console.log(await getItem(BUCKET, FILE)) // <<< await keyword added
}
这仍然在底层使用 Promise,但新语法允许您以一种更自然、更易于理解的方式编写代码。