简体   繁体   中英

Defer an async service call until promise is resolved

I want to create an array of Twilio API calls to be resolved later in Promise.all .

TwilioClient.messages.create(payload) is getting called immediately inside the returned promise (A). How can I defer until the Promise.all chain resolves it (B)?

let twilioTexts = [];
if (twilioNumbers) {
    twilioTexts = twilioNumbers.map(phoneNumber => getTwilioText(mailTokens, phoneNumber));
    // (A) ==> Twilio is sending messages here upon assigning to variable `twilioTexts`.
}

await Promise.all([
  // do other stuff
  ...twilioTexts, // (B) ==> instead, Twilio should make all calls here
]);

...

function getTwilioText(mailTokens, phoneNumber) {
    return new Promise((resolve, reject) => {
        let payload = {
          body: `[Incoming Order!]`,
          from: 'my number',
          to: phoneNumber,
        };

        TwilioClient.messages.create(payload);
    });
}

Edit:

await Promise.all([
  // do other async stuff in parallel
  // check if twilioNumbers then spread map into Promise.all array
  twilioNumbers && ...twilioNumbers.map(phoneNumber => getTwilioText(mailTokens, phoneNumber)),
]);

function getTwilioText(mailTokens, phoneNumber) {
    let payload = {
        body: `[Incoming Order!]`,
        from: 'my number',
        to: phoneNumber,
    };

    return TwilioClient.messages.create(payload);
}

Your second example is almost there, but Promise.all works on an array of promises. The twilioNumbers &&... line produces an array of promises, so you've got an array of promises inside another array, which won't work.

So you can use the spread operator:

await Promise.all([
  // do other stuff
  ...(twilioNumbers 
      ? twilioNumbers.map(phoneNumber => getTwilioText(mailTokens, phoneNumber))
      : []
  ),
]);

...

function getTwilioText(mailTokens, phoneNumber) {
    let payload = {
        body: `[Incoming Order!]`,
        from: 'my number',
        to: phoneNumber,
    };

    return TwilioClient.messages.create(payload);
}

At this point, it's a bit verbose, so you might want to factor that part out:

await Promise.all([
  // do other stuff
  getTwilioTexts(twilioNumbers, mailTokens),
]);

...


// returns a promise for an array
async function getTwilioTexts(numbers, mailTokens) {
    return numbers
        ? Promise.all(numbers.map(num => getTwilioText(mailTokens, num)))
        : [];
}

function getTwilioText(mailTokens, phoneNumber) {
    let payload = {
        body: `[Incoming Order!]`,
        from: 'my number',
        to: phoneNumber,
    };

    return TwilioClient.messages.create(payload);
}

You seem to be looking for

const otherPromises = // do other stuff, *triggered first*
const twilioTexts = (twilioNumbers || []).map(phoneNumber => getTwilioText(mailTokens, phoneNumber));

await Promise.all([
  ...otherPromises,
  ...twilioTexts,
]);

Ultimately, it shouldn't matter though as you want to run the other stuff concurrently with sending texts anyway.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM