美文网首页程序员饥人谷技术博客JavaScript 进阶营
记一次错:循环中调用 Promise 的 resolve 的问题

记一次错:循环中调用 Promise 的 resolve 的问题

作者: 写代码的海怪 | 来源:发表于2019-01-19 13:38 被阅读6次

起因

最近在看方方的《造轮子》,我是直接上 vue-cli 3 的,所以在配置上真的下了很大功夫。今天就出现了在循环里调用 resolve 函数的问题。

先说说我的配置吧,我是使用 vue-cli 3 + vue-cli-plugin-unit-karma 插件来配置的 Karma 的。

vue.config.js

vue-cli 3 是不需要 webpack.config.js 的,所以要将配置 Karam 要使用 vue-cli-plugin-unit-karma 插件,这也是官方推荐的方法,而且这个插件是和 vue-cli-service 配合的连 package.json 里的 test 都不用改,直接 vue-cli-service test:unit 一波带走。这里面我还使用了全局 Sass 文件。

const karmaConfig = require('./karma.config')
module.exports = {
    publicPath: process.env.NODE_ENV === 'production'
        ? '/overwatch-ui/'
        : '/',
    css: {
        loaderOptions: {
            sass: {
                // @ -> /src
                data: `
                    @import "@/assets/styles/global.scss";
                    @import "@/assets/styles/reset.scss";
                `
            }
        }
    },
    pluginOptions: {
        karma: {
            expressServer: undefined,

            karmaConfig: karmaConfig
        }
    }
}

karam.config.js

注意,这不是官方所用的那种 karam.config.js 文件,我的文件只是返回一个对象,不想在 vue.config.js 里写太长了而已。

module.exports = {
    basePath: '',
    frameworks: ['mocha', 'chai', 'sinon-chai'],
    client: {
        chai: {
            includeStack: true
        },
    },
    files: [
        'tests/**/*.spec.js',
        'tests/**/*.spec.ts',
    ],
    reporters: ['progress'],
    port: 9876,
    colors: true,
    autoWatch: true,
    browsers: ['ChromeHeadless'],
    concurrency: Infinity,
}

Input.spec.js

先定义一下 testProperty 函数,因为我理想的情况是多种值都要测,所以应该循环一个数组,对数组里每个值都做一次测试(就是这个代码坑了,用回调好好的,自己非得装B用 Promise 来玩)。

function testProperty(values) {
    return new Promise((resolve, reject) => {
        values.forEach((value) => resolve(value))
    })
}

这里我就不写那么多代码啦,大家看到这就意会一下就行了。

describe('events', ()=> {
    it('can be handled', () => {
        const events = ['click', 'change', 'input']
        const eventHandler = sinon.stub()

        testProperty(events)
            .then((eventName) => {
                console.log(eventName)
                const InputVue = shallowMount(Input, {
                    listeners: {
                        [`${eventName}`]: eventHandler
                    }
              })

            InputVue.find('input').trigger(eventName)

            expect(eventHandler.called).to.equal(true)
        })
    })
})

说完上面的基本配置,就说说今天的采坑记吧。

没有 Log?

当我运行 yarn run test 的时候,发现 Karma 跑通了,Yes,第一波 Vue + Karam 配置成功!

哎不对,我的 console.log(eventName) 怎么没了?第一反应是 Karam 没有配置好,因为测试是归 Karma 管的。然后 Google 了一下,找到了 Karam runner 里 Karam-Mocha 里的 Issue

然后马上去将 browserConsoleLogOptionscaptureConsole 里的东西加在 karam.config.js 里。再次运行,Boom,还是不行,什么都没有打印。

config 是谁,它在哪?

虽然这个人很多赞,但是毕竟是个人说辞,不太可靠,他既然说到了 Karma 的配置,那么官方文档肯定会有说呀。Go,下一步 Karam 官方文档。果然我找到一个配置:

说是在 karam.config.js 里设置 config.LOG_INFO 的,像这样:

module.exports = function(config) {
  config.set({
    logLevel: config.LOG_INFO,
  });
};

但是,这种是不是 vue cli 3 的写法,这是 vue cli + webpack.config.js 的写法呀。我了个去,这么写 config 都不知道从哪来,常量 LOG_INFO 肯定是 undefined

哎,虽然我不能配置 logLevel: config.LOG_INFO,但是我可以用命令行呀,所以马上去 package.json 里改脚本命令:

"test": "vue-cli-service test:unit --log-level debug"

开 iTerm2,秒写命令:

yarn run test

但是还是没 log,当时心态已经到崩溃的边缘了。

484你这个 0.5 版本的插件不行啊

现在头号嫌疑犯就是这个插件了,因为 --log-level debug 写在 vue-cli-service 后面,应该是要 vue-cli-service 结合使用的,而这个插件号称自己和 vue-cli-service 完美结合,一看版本才 0.5 想:是不是你这个弱智没写好插件就到处装B了。又去看了这个插件的 Issue。

嗯。。。还很干净。没法了,现在只有两条路

  1. 写 Issue 给这个插件作者,可能要等一会才能解决,而且不一定能解决。
  2. 使用降级 vue-cli,使用 vue-cli 和 webpack.config.js 结合的老方法,一定能行,但是麻烦。

两个方法都很难受,所以我选择了第三种方法:在别的地方打 log,是不是真的别的地方都不能打 log 了。所以我在 testProperty 里加了句:

function testProperty(values) {
    return new Promise((resolve, reject) => {
        console.log(values)
        values.forEach((value) => resolve(value))
    })
}

结果竟然有 log 了!看来上面的方法全部作废了,别的地方能 log 说明配置完全正确。

循环 resolve 害死人啊

其实我一开始写的 testProperty 是这样的:

function testProperty(values, callback) {
    values.forEach(callback)
}

我想了想,是不是有点 low 啊,这样封装好像都没什么意义,所以使用了 Promise 写法。而这种写法只能在循环里调用 resolve(value) 才能将数组元素传入回调里。后面自己再试了试,then() 完了之后只会调用一次 resolve(value),而不会在循环里多次调用,我的这种写法纯粹属性猜测去写,所以导致看了半天的 Issue 和 StackOverflow 才慢慢解决了这个问题。

总结

其实我的循环调用 resolve 是可以打出一个 log 的,因为会调用一次,但是前期确实没有将 karam.config.js 里的 clientbrowserConsoleLogOptions 配置好,所以没有 log。

即使加了这个配置选项,可能当时代码本来也点问题,所以一直没发现这种”猜测写法“带来的问题。最后解决的时候确实能回想当初写这样代码的想法:“能不能循环 resolve 呢?嗯试试吧”。

总之,这是一次不错的调错经历,调完真的是身心俱疲。

相关文章

  • 记一次错:循环中调用 Promise 的 resolve 的问题

    起因 最近在看方方的《造轮子》,我是直接上 vue-cli 3 的,所以在配置上真的下了很大功夫。今天就出现了在循...

  • Promise小结

    Promise 1、怎么使用Promise 任务成功调用 resolve(result)任务失败调用 reject...

  • promise reject

    1.promise((resolve, reject) =>{}), 逻辑中必须调用resolve 或 rejec...

  • 28.Promise链式调用的写法

    promise链式调用resolve的写法 有三种方式: 直接new一个新的Promise对象 通过Promise...

  • Promise

    调用resolve或reject并不会终结 Promise 的参数函数的执行。 Promise 对象的错误具有“冒...

  • promise then catch 状态改变

    总结 promise resolve 后,会变为resloved状态,此时会调用then 方法,调用then会默认...

  • JavaScript同步--Promise

    1. 创建Promise resolve : 执行成功调用方法reject : 执行失败调用方法 2. 使用Pro...

  • 手写promise

    这里是鄙人博客中《手写 Promise》的传送门 1.解决异步调用resolve、reject问题使用类似订阅发布...

  • js.Promise resolve()

    功能一:Promise.resolve();立即让promise进行resolve的状态,并返回Promise 相...

  • Promise详解

    Promise详解词:Promise,resolve,reject,Prepending,Resolve,Reje...

网友评论

    本文标题:记一次错:循环中调用 Promise 的 resolve 的问题

    本文链接:https://www.haomeiwen.com/subject/lznadqtx.html