var saved = new Date();
setTimeout(() => console.log(saved, new Date()), 1000);
setTimeout(() => console.log(saved, new Date()), 2000);
在任何javascript引擎上执行此原始脚本,您将看到这样的输出(查看秒数):
2018-02-21T22:50:29.066Z 2018-02-21T22:50:30.071Z
2018-02-21T22:50:29.066Z 2018-02-21T22:50:31.070Z
第一列中的所有日期都相同(因为它是唯一的SAVED日期)。
但是如果您在Google应用脚本中执行类似的脚本:
///// code.gs /////
function doGet() { // a main window maker
return HtmlService.createTemplateFromFile('index').evaluate();
}
var saved = new Date(); // <<< our hero
function getDates() {
return JSON.stringify({saved: saved, now: new Date()});
///// index.html /////
look at your browser console
<script>
setTimeout(() => google.script.run
.withSuccessHandler(console.log)
.getDates()
, 1000);
setTimeout(() => google.script.run
.withSuccessHandler(console.log)
.getDates()
, 2000);
</script>
你会看到这样的输出(看秒):
{"saved":"2018-02-21T23:03:58.663Z","now":"2018-02-21T23:03:58.664Z"}
{"saved":"2018-02-21T23:03:59.655Z","now":"2018-02-21T23:03:59.656Z"}
每当您通过google.script.run从客户端调用服务器脚本时,变量saved
正在更新!!!
怎么了?我怎么能避免这个?
答案 0 :(得分:4)
Google Script中的运行之间没有任何内容。从这个意义上说,这是一个预期的结果。它必须设置一个新的getDates()
值,否则在函数saved
内部甚至不会声明变量.setHours()
。如果您希望实际存储一个值用于多次运行,则需要使用PropertiesService或使用#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#ifdef __cplusplus
#include <vector>
#else // C
#include <stdbool.h> // For adding boolean support
#endif // __cplusplus
// Convenience define for cleanup
#define _CLEANUP_IF(a) if ((a)) goto Cleanup;
#ifdef __cplusplus
// Wrap into class in case of C++
class Sha256Calculator {
public:
#endif // __cplusplus
// Calculates SHA256 hash from given array of data and returns array
// Note: Parameter "outHash" is manually allocated so consider calling free(outHash) after using it
static bool calculateSha256(uint8_t** outHash, size_t* outHashSize, const uint8_t *data, const size_t dataSize)
{
bool result = false;
CFErrorRef error = NULL;
SecTransformRef digestTransform = NULL;
CFDataRef sourceData = NULL;
CFDataRef outDataRef = NULL;
const UInt8 * outData = NULL;
CFIndex outDataSize = 0;
// Create a CFData object from the source
sourceData = CFDataCreate(kCFAllocatorDefault, (const UInt8*)data, dataSize);
_CLEANUP_IF(!sourceData);
digestTransform = SecDigestTransformCreate(kSecDigestSHA2, 256, &error);
_CLEANUP_IF(error);
SecTransformSetAttribute(digestTransform, kSecTransformInputAttributeName, (CFDataRef)sourceData, &error);
_CLEANUP_IF(error);
outDataRef = (CFDataRef)SecTransformExecute(digestTransform, &error);
_CLEANUP_IF(error);
_CLEANUP_IF(!outDataRef);
// Extract data from CFDataRef to array
outData = CFDataGetBytePtr(outDataRef); // Returns read-only (UInt8*) pointer to the data
outDataSize = CFDataGetLength(outDataRef);
if (outHash) {
*outHash = (uint8_t*)malloc(outDataSize);
if (*outHash) {
memcpy(*outHash, outData, outDataSize);
if (outHashSize) {
*outHashSize = (size_t)outDataSize;
}
result = true;
}
}
// Notes:
// * All the objects are released except "outData" since it's handled and cleaned by using outDataRef
// * CFRelease throws error if the passed object is NULL, so check objects before releasing
Cleanup:
// Use CFShow(error) for getting details about error
if (error) { CFRelease(error); }
if (digestTransform) { CFRelease(digestTransform); }
if (sourceData) { CFRelease(sourceData); }
if (outDataRef) { CFRelease(outDataRef); }
return result;
}
#ifdef __cplusplus
// Convenience method for cpp using vectors
static bool calculateSha256(std::vector<uint8_t>& outHash, const std::vector<uint8_t>& data)
{
// Call original method
uint8_t * outHashArray = nullptr;
size_t outHashSize;
bool result;
result = calculateSha256(&outHashArray, &outHashSize, data.data(), data.size());
if (!result)
return false;
// Put resulting array in vector
outHash.clear();
outHash.insert(outHash.end(), &outHashArray[0], &outHashArray[outHashSize]);
// Clean allocated array
if (outHashArray)
free(outHashArray);
return result;
}
};
#endif // __cplusplus
设置实际设置值,依此类推。