promise.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /* Promise Library v1.1 for GUN DB
  2. * Turn any part of a gun chain into a promise, that you can then use
  3. * .then().catch() pattern.
  4. * In normal gun doing var item = gun.get('someKey'), gun returns a reference
  5. * to the someKey synchroneously. Using a reference is quite helpful in making
  6. * graph structures, so I have chosen to follow the following paradigm.
  7. * Whenever a promise is resolved, gun will return an object of data, I will
  8. * wrap that data in an object together with the reference like so:
  9. * {ref: gunRef, data: data}.
  10. * This code is freely given in the spirit of open source MIT license.
  11. * Author: Jachen Duschletta / 2019
  12. */
  13. /*
  14. * Function promOnce
  15. * @param limit - due to promises resolving too fast if we do not set a timer
  16. * we will not be able receive any data back from gun before returning the promise
  17. * works both following a Chain.get and a Chain.map (limit only applies to map)
  18. * If no limit is chosen, defaults to 100 ms (quite sufficient to fetch about 2000 nodes or more)
  19. * @param opt - option object
  20. * @return {ref: gunReference, data: object / string (data), key: string (soulOfData)}
  21. */
  22. Gun.chain.promOnce = async function (limit, opt) {
  23. var gun = this, cat = gun._;
  24. if(!limit){limit = 100}
  25. if(cat.subs){
  26. var array = [];
  27. gun.map().once((data, key)=>{
  28. var gun = this;
  29. array.push(new Promise((res, rej)=>{
  30. res({ref: gun, data:data, key:key});
  31. })
  32. )
  33. }, opt);
  34. await sleep(limit);
  35. return Promise.all(array)
  36. } else {
  37. return (new Promise((res, rej)=>{
  38. gun.once(function (data, key) {
  39. var gun = this;
  40. res({ref:gun,data:data,key:key});
  41. }, opt);
  42. }))
  43. }
  44. var chain = gun.chain();
  45. return chain;
  46. }
  47. function sleep (limit) {
  48. return (new Promise((res, rej)=>{
  49. setTimeout(res, limit);
  50. }))
  51. }
  52. /*
  53. * Function promPut
  54. * @param item (string / object) - item to be put to that key in the chain
  55. * @param opt - option object
  56. * @return object - Returns an object with the ref to that node that was just
  57. * created as well as the 'ack' which acknowledges the put was succesful
  58. * object {ref: gunReference, ack: acknowledgmentObject}
  59. * If put had an error we can catch the return via .catch
  60. */
  61. Gun.chain.promPut = async function (item, opt) {
  62. var gun = this;
  63. return (new Promise((res, rej)=>{
  64. gun.put(item, function(ack) {
  65. if(ack.err){console.log(ack.err); ack.ok=-1; res({ref:gun, ack:ack})}
  66. res({ref:gun, ack:ack});
  67. }, opt);
  68. }))
  69. }
  70. /*
  71. * Function promSet
  72. * @param item (string / object) - item to be set into a list at this key
  73. * @param opt - option object
  74. * @return object - Returns object with the ref to that node that was just
  75. * created as well as the 'ack' which acknowledges the set was succesful
  76. * object {ref: gunReference, ack: acknowledgmentObject}
  77. * If set had an error we can catch the return via .catch
  78. */
  79. Gun.chain.promSet = async function(item, opt){
  80. var gun = this, soul;
  81. var cb = cb || function(){};
  82. opt = opt || {}; opt.item = opt.item || item;
  83. return (new Promise(async function (res,rej) {
  84. if(soul = Gun.node.soul(item)){ item = Gun.obj.put({}, soul, Gun.val.link.ify(soul)) }
  85. if(!Gun.is(item)){
  86. if(Gun.obj.is(item)){;
  87. item = await gun.back(-1).get(soul = soul || Gun.node.soul(item) || gun.back('opt.uuid')()).promPut(item);
  88. item = item.ref;
  89. }
  90. res(gun.get(soul || (Gun.state.lex() + Gun.text.random(7))).promPut(item));
  91. }
  92. item.get(function(soul, o, msg){
  93. var ack = {};
  94. if(!soul){ rej({ack:{err: Gun.log('Only a node can be linked! Not "' + msg.put + '"!')}} ) }
  95. gun.put(Gun.obj.put({}, soul, Gun.val.link.ify(soul)), cb, opt);
  96. },true);
  97. res({ref:item, ack:{ok:0}});
  98. }))
  99. }
  100. /*
  101. * Function promOn
  102. * @param callback (function) - function to be called upon changes to data
  103. * @param option (object) - {change: true} only allow changes to trigger the callback
  104. * @return - data and key
  105. * subscribes callback to data
  106. */
  107. Gun.chain.promOn = async function (callback, option) {
  108. var gun = this;
  109. return (new Promise((res, rej)=>{
  110. gun.on(function (data, key){
  111. callback(data, key);
  112. res(data, key);
  113. }, option);
  114. }));
  115. }