云可调用函数中的返回日期/服务器时间戳 [英] Returning dates / server timestamps in cloud callable functions

查看:61
本文介绍了云可调用函数中的返回日期/服务器时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用客户端应用程序中的可调用函数来从Firestore中检索一些数据.数据是使用以下方式创建的:

I'm using a callable function from a client app to retrieve some data from firestore. The data is created using:

projectData = {
  created: firebase.firestore.FieldValue.serverTimestamp(),
  ...otherData
}
firebase.firestore().collection(projectsCollection).add(projectData)

我可以看到时间戳正确地保存在了Firestore控制台中.可调用函数还有其他功能,并且具有错误处理功能,但是数据检索是这样完成的(使用lodash将每个文档扩展为一个对象以返回到客户端):

And I can see the timestamp is correctly saved in the firestore console. The callable function does some other things and has error handling, but the data retrieval is done like this (using lodash to expand each document into an object to return to the client):

const projectRef = firestore.collection(gProjectsCollection).orderBy('created')
return projectRef.get().then(snapshot => {
  return {
    projects: _.chain(snapshot.docs)
      .keyBy('id')
      .mapValues(s => s.data())
      .value()
  }
})

这通常有效,但是返回的对象具有一个损坏的 created 属性(如此处显示在函数shell输出中):

This mostly works, but the returned object has a mangled created property (shown here in functions shell output):

RESPONSE RECEIVED FROM FUNCTION: 200, {
  "result": {
     "projects": {
      "XcRyQyaxLguRdbNmxQdn": {
        "name": "c",
        "description": "c",
        "created": {
          "_seconds": 1543405587,
          "_nanoseconds": 169000000
        }
      }
    }
  }
}

我认为这是因为可调用函数在内部使用了 JSON.stringify(),并且服务器时间戳未正确转换.我尝试将时间戳明确转换为这样的日期:

I'm presuming this is because the callable function uses JSON.stringify() internally, and the server timestamp isn't converted correctly. I tried explicitly converting the timestamp to a date like this:

return projectRef.get().then(snapshot => {
  return {
    exVersion,
    exId,
    projects: _.chain(snapshot.docs)
      .keyBy('id')
      .mapValues(s => s.data())
      .forEach(d => { d.created = d.created.toDate() })
      .value()
  }
})

但是现在我得到了一个空对象:

but now I get an empty object back:

RESPONSE RECEIVED FROM FUNCTION: 200, {
  "result": {
    "projects": {
      "XcRyQyaxLguRdbNmxQdn": {
        "name": "c",
        "description": "c",
        "created": {}
      }
    }
  }
}

我怀疑这里的真正问题是可调用函数未设置为返回日期对象.如果再走一步并将时间戳记转换为字符串,那么我最终会在客户端获得一些信息:

I suspect the real problem here is that callable functions aren't set up to return date objects. If I go one more step and convert the timestamp into a string, I finally get something back in the client:

return projectRef.get().then(snapshot => {
  return {
    exVersion,
    exId,
    projects: _.chain(snapshot.docs)
      .keyBy('id')
      .mapValues(s => s.data())
      .forEach(d => { d.created = d.created.toDate().toISOString() })
      .value()
  }
})

给予:

RESPONSE RECEIVED FROM FUNCTION: 200, {
  "result": {
    "exVersion": 9,
    "exId": null,
    "projects": {
      "XcRyQyaxLguRdbNmxQdn": {
        "name": "c",
        "description": "c",
        "created": "2018-11-28T11:46:27.169Z"
      }
    }
  }
}

我在可调用函数的文档中找不到关于日期的特殊处理的任何内容,但是我在应如何做方面缺少什么?

I couldn't find anything in the documentation for callable functions about special handling for dates, but am I missing something in how this should be done?

可调用函数中的一些进一步分析表明,涉及到了 JSON.stringify(),但并不是全部问题:

Some further analysis in the callable function suggests JSON.stringify() is involved, but isn't the whole problem:

console.log(JSON.stringify(d.created)):
info: {"_seconds":1543405587,"_nanoseconds":169000000}
JSON.stringify(d.created.toDate())
into: "2018-11-28T11:46:27.169Z"

因此,调用 d.created.toDate() 应该就足够了.但是我还有其他情况,其中 Date 对象只是不由可调用函数返回,例如:

So calling d.created.toDate() should be sufficient. But I've had other cases where Date objects are just not returned by callable functions, e.g.:

const testObject = {
  some: 'thing',
  d: new Date()
}

console.log('JSON:', JSON.stringify(testObject))

  return projectRef.get().then(snapshot => {
    return {
      testObject,
      projects: _.chain(snapshot.docs)
        .keyBy('id')
        .mapValues(s => s.data())
        .forEach(d => { console.log('d.created is:', JSON.stringify(d.created.toDate())); d.created = d.created.toDate() })
        .value()
    }
  })

请注意,在下面的输出中,日期对象上的 JSON.stringify()记录的结果似乎有效,但是当这些对象包含在从函数返回的对象中时,它们都会出现作为空对象:

Note in the output below, the logged results of JSON.stringify() on date objects seems to work, but when those objects are contained within the object returned from the function, they both come out as empty objects:

firebase > getAllProjects({uid: 1234})
Sent request to function.
firebase > info: User function triggered, starting execution
info: JSON: {"some":"thing","d":"2018-11-28T13:22:36.841Z"}
info: Got 1 projects
info: d.created is: "2018-11-28T11:46:27.169Z"
info: Execution took 927 ms, user function completed successfully

RESPONSE RECEIVED FROM FUNCTION: 200, {
  "result": {
    "testObject": {
      "some": "thing",
      "d": {}
    },
    "projects": {
      "XcRyQyaxLguRdbNmxQdn": {
        "description": "c",
        "created": {},
        "name": "c"
      }
    }
  }
}

推荐答案

来自文档:

要将数据发送回客户端,请返回可以JSON编码的数据.

To send data back to the client, return data that can be JSON encoded.

由于 <日期>日期不是JSON类型,因此您必须使用自己的序列化格式它(至少如果您希望它可靠/便携).在链接的答案中,这听起来像是 Date.toJSON 是一个很好的选择.

Since Date is not a JSON type, you will have to use your own serialization format for it (at least if you want it to be reliable/portable). From the linked answer it sounds like Date.toJSON is a great candidate for that.

这篇关于云可调用函数中的返回日期/服务器时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆