liuguanyu / quiz-every-meeting

8 stars 0 forks source link

2018-07-31 Promise的依顺序执行 #24

Open liuguanyu opened 6 years ago

liuguanyu commented 6 years ago

对于一组Promise数组,如果是并行求最终结果,当然可以使用Promise.all来执行。此时运行顺序是并行的,执行顺序是随机的。 但是,我们常常遇到一种情况,一个Promise数组如promises,要求他们是按顺序执行的,当第一个promise成功之后,第二个开始执行,直至最后一个。为了实现这个需求,你当然可以使用async/await来执行。那么,当不允许使用async/await时候,请你写出这个函数,sequencePromise(promises),返回一个promise, 成功的值是最后一个promise的结果,失败打印失败。

上面这道题有问题,promise被构造会立即执行,我修改一下表述方式:

对于一组网址,如果是并行请求最终结果,当然可以使用Promise.all来构造promise执行request。此时运行顺序是并行的,执行顺序是随机的。

但是,我们常常遇到一种情况,一个url数组如urls,要求他们是按顺序请求的,当第一个url成功之后,第二个开始请求,直至最后一个。为了实现这个需求,你当然可以使用async/await来执行。那么,当不允许使用async/await时候,请你写出这个函数,sequenceRequest(urls),返回一个promise, 成功的值是按顺序所有url的结果,任何一个失败打印失败。

chunpu commented 6 years ago

如果 promise 已经被构造出来了, 可以先不执行吗?

liuguanyu commented 6 years ago

@chunpu 你说的有道理,我修改下题目。

chunpu commented 6 years ago
sequence([100, 300, 200]).then(result => {
    console.log('result', result)
})

function deplay(time) {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(time)
            resolve(time)
        }, time)
    })
}

function sequence(arr) {
    return arr.reduce((ret, item, index) => {
        return ret.then(data => deplay(item).then(val => {
            data[index] = val
            return data
        }))
    }, Promise.resolve([]))
}
wuxueguang commented 6 years ago
function sequenceRequest(urls) {
    let results = []
    let errs = []
    let promise = Promise.resolve(results)

    return promise = urls.reduce((p, url) => {
        return p.then(results => {
            return new Promise((resolve, reject) => {
                return doAjax(url).then(dat => {
                    results.push(`${url}: ${dat}`)
                    resolve(results)
                }).catch(err => {
                    errs.push(`${url}: ${err}`)
                    reject(errs)
                })
            })
        }).catch(errs => {
            return Promise.reject(errs)
        })
    }, promise);
}

function doAjax(url) {
    return new Promise((resolve, reject) => {
        console.log(url, 'start ...')
        setTimeout(() => {
            let v = Math.random()
            if (v > 0.5) {
                resolve('Success!')
                console.log(url, 'succeeded!')
            } else {
                reject('Fail!')
                console.log(url, ' failed!')
            }
        }, 1000)
    })
}

sequenceRequest(['a', 'b'])
    .then(ret => console.log(ret))
    .catch(errs => console.log(errs))

是这个意思么?