Web3.js: BatchRequest return promise

Created on 12 Mar 2018  ·  16Comments  ·  Source: ChainSafe/web3.js

Currently the BatchRequest object has an execute function. This function will execute the batch request (presumably in order, although the documentation does not say so). The script which calls execute does not learn that execution has occurred and therefore the process will hang because you cannot call process.exit().

Returning a promise would fix that.

enhancement

Most helpful comment

Hey all - I've implemented a helper function here that is a promise-oriented API:

function makeBatchRequest(calls) {
    let batch = new web3.BatchRequest();

    let promises = calls.map(call => {
        return new Promise((res, rej) => {
            let req = call.request(params, (err, data) => {
                if(err) rej(err);
                else res(data)
            });
            batch.add(req)
        })
    })
    batch.execute()

    return Promise.all(promises)
}

// Usage
let [
    returnValueFromCall,
    publicProp,
    txid
] = await makeBatchRequest([
    contract.methods.getSomething().call,
    contract.methods.publicProp().call,
    contract.methods.makeAChange().send
])

Works with call and send.

All 16 comments

any news?

Hey all - I've implemented a helper function here that is a promise-oriented API:

function makeBatchRequest(calls) {
    let batch = new web3.BatchRequest();

    let promises = calls.map(call => {
        return new Promise((res, rej) => {
            let req = call.request(params, (err, data) => {
                if(err) rej(err);
                else res(data)
            });
            batch.add(req)
        })
    })
    batch.execute()

    return Promise.all(promises)
}

// Usage
let [
    returnValueFromCall,
    publicProp,
    txid
] = await makeBatchRequest([
    contract.methods.getSomething().call,
    contract.methods.publicProp().call,
    contract.methods.makeAChange().send
])

Works with call and send.

Hey all - I've implemented a helper function here that is a promise-oriented API:

function makeBatchRequest(calls) {
    let batch = new web3.BatchRequest();

    let promises = calls.map(call => {
        return new Promise((res, rej) => {
            let req = call.request(params, (err, data) => {
                if(err) rej(err);
                else res(data)
            });
            batch.add(req)
        })
    })
    batch.execute()

    return Promise.all(promises)
}

// Usage
let [
    returnValueFromCall,
    publicProp,
    txid
] = await makeBatchRequest([
    contract.methods.getSomething().call,
    contract.methods.publicProp().call,
    contract.methods.makeAChange().send
])

Works with call and send.

Example, setting 'params' from example above as the account to make the call to web3 from in each batched call...

function makeBatchRequest(web3, calls, callFrom) {
    let batch = new web3.BatchRequest();
    let promises = calls.map(call => {
        return new Promise((resolve, reject) => {
            let request = call.request({from: callFrom}, (error, data) => {
                if(error) {
                    reject(error);
                } else {
                    resolve(data);
                }
            });
            batch.add(request);
        });
    });

    batch.execute();

    return Promise.all(promises);
}

Watch your gas costs - have run some tests and this code has a huge gas cost for some reason!

Issue Status: 1. Open 2. Started 3. Submitted 4. Done


__This issue now has a funding of 60.0 DAI (60.0 USD @ $1.0/DAI) attached to it as part of the Ethereum Foundation fund.__

If someone will do a PR for this issue because of the gitcoin bounty then please to the PR against the ethereumProvider branch.

@liamzebedee Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!

  • [x] reminder (3 days)
  • [ ] escalation to mods (6 days)

Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days

Haha, @gitcoinbot you're getting better! Thanks Mom ;P

WIP PR here - #2111 - docs a bit out of date but I think I'll manage

@liamzebedee Hello from Gitcoin Core - are you still working on this issue? Please submit a WIP PR or comment back within the next 3 days or you will be removed from this ticket and it will be returned to an ‘Open’ status. Please let us know if you have questions!

  • [x] reminder (3 days)
  • [ ] escalation to mods (6 days)

Funders only: Snooze warnings for 1 day | 3 days | 5 days | 10 days | 100 days

Just started writing with the new testing format. Looking good but getting:

 FAIL  tests/src/providers/BatchRequestTest.js
  ● Test suite failed to run

    Cannot find module 'underscore-es/isFunction' from 'web3-net.cjs.js'

       9 | var Utils = require('web3-utils');
      10 | var web3Core = require('web3-core');
    > 11 | var isFunction = _interopDefault(require('underscore-es/isFunction'));
         |                                  ^
      12 | var web3CoreMethod = require('web3-core-method');
      13 |
      14 | function _classCallCheck(instance, Constructor) {

      at Resolver.resolveModule (../../node_modules/jest-resolve/build/index.js:221:17)
      at Object.require (../web3-net/dist/web3-net.cjs.js:11:34)

Any ideas? I'm running node --inspect-brk ./node_modules/.bin/jest --runInBand BatchRequest from packages/web3-providers

@liamzebedee Yes, I'm currently improving the web3 providers and also refactored the BatchRequest object. Will update the tests today and finish my refactoring.

Unfortunately, I already implemented the Promise for a BatchRequest execution 🙈 (#2000)

Ok well thanks for letting me know.

I wrapped BatchRequest

function PromisifyBatchRequest() {
    this.batch = new web3.BatchRequest;
    this.requests = [];
}

PromisifyBatchRequest.prototype.add = function (_request, ...params) {
    let that = this;
    let request = new Promise((resolve, reject) => {
        that.batch.add(_request.call(null, ...params, (err, data) => {
            if (err) return reject(err);
            resolve(data);
        }));
    });
    this.requests.push(request);
};

PromisifyBatchRequest.prototype.execute = async function () {
    this.batch.execute();
    return await Promise.all(this.requests);
};

and example

let batch = new PromisifyBatchRequest();
batch.add(web3.eth.getTransactionReceipt.request, '0x497e971e8c024f4d6aecf33f1b4d104ebb1febe8ffd085cec44389c23f569635');
batch.add(web3.eth.getTransactionReceipt.request, '0x08d1482c9752b60396c29efd556c1379295e48036b8e9386eada09cd42dbd77f');

let receipts = await batch.execute();
console.log(receipts, receipts.length);

Options

You can replace it if this works

new web3.BatchRequest = wrap(web3)...

@fulldecent cloud you please let someone can close the gitcoin bounty, it still opening even the issue has always resolved by @nivida.

Issue Status: 1. Open 2. Cancelled


__The funding of 60.0 DAI (60.0 USD @ $1.0/DAI) attached to this issue has been cancelled by the bounty submitter__

Closed because it got already implemented in the PR #2000.

Was this page helpful?
0 / 5 - 0 ratings