promise顺序控制
发布于 7 年前 作者 leavesdrift 3158 次浏览 来自 问答
/**
 * This example prints :
 *
 *   -----------
 *   -----------
 *   -----------
 *   -----------
 *   Resolved HTTP Call
 *   0
 *   Resolved HTTP Call
 *   2
 *   Resolved HTTP Call
 *   0
 *   Resolved HTTP Call
 *   1
 *   Resolved HTTP Call
 *   2
 *   Resolved HTTP Call
 *   1
 *   Resolved HTTP Call
 *   1
 *   Resolved HTTP Call
 *   0
 *   Resolved HTTP Call
 *   2
 *
 * Fix the `Tester` class in order to have it print :
 *
 *   -----------
 *   Resolved HTTP Call
 *   0
 *   Resolved HTTP Call
 *   1
 *   Resolved HTTP Call
 *   2
 *   -----------
 *   Resolved HTTP Call
 *   0
 *   [...]
 *
 * Feel free to implement/modify any methods that are relevant. DO NOT modify the `getUrl` method.
 */

const http = require('http')

class Tester {
  constructor(firstUrl, secondUrl, thirdUrl) {
    console.info('-----------')

    for(let i = 0; i < 3; i++) {
      console.info('-----------')
      this.run([firstUrl, secondUrl, thirdUrl])
    }
  }

  run(urls) {
    urls.forEach((url, index) => {
      this.getUrl(url, index)
        .then(this.print)
    })
  }

  getUrl(url, index) {
    return new Promise((resolve, reject) => {
      let timeout = Math.floor(Math.random() * (500 - 3000 + 1)) + 3000
      setTimeout(() => {
        http.get(url, (res) => {
          console.info('Resolved HTTP Call')
          resolve(index)
        });
      }, timeout)
    })
  }

  print(value) {
    console.info(value)
  }
}

const tester = new Tester(
  'http://httpbin.org/ip',
  'http://httpbin.org/user-agent',
  'http://httpbin.org/headers')

6 回复

这道题怎么让它正确形式输出呢?

正确结果应该是这种形式:

 -----------
 *   Resolved HTTP Call
 *   0
 *   Resolved HTTP Call
 *   1
 *   Resolved HTTP Call
 *   2
 *   -----------
 *   Resolved HTTP Call
 *   0
 *   [...]

想了挺久不知道怎么在不改变 getUrl 函数的情况下达到这种形式的输出

最后自己尝试着解决了,这是其中一种方案:

const http = require('http')

class Tester {
  constructor(firstUrl, secondUrl, thirdUrl) {

    let promise = Promise.resolve()
       ,self = this

    let sep = function(){
     return new Promise((resolve,reject) => {
          console.info('----------')
          resolve()
       })
    }

    for(let i = 0; i < 3; i++) {
      promise = promise.then(sep)

      let arr = [firstUrl, secondUrl, thirdUrl]

        arr.forEach((url,index) => {
          promise = promise.then(function(){return self.getUrl(url,index).then(self.print)})
        })

      }

  }

  getUrl(url, index) {
    return new Promise((resolve, reject) => {
      let timeout = Math.floor(Math.random() * (500 - 3000 + 1)) + 3000
      setTimeout(() => {
        http.get(url, (res) => {
          console.info('Resolved HTTP Call')
          resolve(index)
        });
      }, timeout)
    })
  }

  print(value) {
    console.info(value)
  }
}

const tester = new Tester(
  'http://httpbin.org/ip',
  'http://httpbin.org/user-agent',
  'http://httpbin.org/headers')

你这是并发的,就不能保证顺序。

要改成串联式的

来自酷炫的 CNodeMD

提示一下,可以用队列控制,控制promise也行,控制结果输出也可以。但注意 * Feel free to implement/modify any methods that are relevant. DO NOT modify the getUrl method.

const http = require('http')

class Tester {
    constructor(...urls) {
        console.info('-----------')

        this.run(urls, 3)
    }

    async run(urls, count) {
        for (let i = 0; i < count; i++) {
            for (let j = 0; j < urls.length; j++) {
                await this.getUrl(urls[j], j)
                    .then(this.print)
            }
        }
    }

    getUrl(url, index) {
        return new Promise((resolve, reject) => {
            let timeout = Math.floor(Math.random() * (500 - 3000 + 1)) + 3000
            setTimeout(() => {
                http.get(url, (res) => {
                    console.info('Resolved HTTP Call')
                    resolve(index)
                });
            }, timeout)
        })
    }

    print(value) {
        console.info(value)
    }
}

const tester = new Tester(
    'http://httpbin.org/ip',
    'http://httpbin.org/user-agent',
    'http://httpbin.org/headers')
回到顶部